【问题标题】:How to bypass conversion const char* to int如何绕过转换 const char* 到 int
【发布时间】:2018-09-16 15:59:05
【问题描述】:

我想写一个函数

template <class Arg>
tuple<int, double> calc(Arg arg);

返回:

[arg,0] if arg is int,
[0,arg] if arg is double 
and [0,0] if arg is nor int or double. 

我实现了这个函数比较arg的类型(Arg)、i的类型(int)和d的类型(double) 然后分别等于 i=arg 或 d=arg。 但是,如果我想将我的函数与无法转换为 int/double 的字符串或其他类型一起使用,则会出现转换错误(例如,很明显,因为我不能将 char* 等同于 int)。 我怎样才能绕过这个转换 const char* 到 int(或另一个不可转换的类型到 int)?或者也许这个函数还有另一个实现?

#define GETTYPE(x) typeid(x).name()
template <class Arg>
    tuple<int,double> calc(Arg arg)
    {
        int i = 0;
        double d = 0;
        if (GETTYPE(arg) == GETTYPE(i))
        {
            i = arg;
        }
        else if (GETTYPE(arg) == GETTYPE(d))
        {
            d = arg;
        }
        return make_tuple(i, d);
    }

【问题讨论】:

  • 不要使用typeid::name。这种情况下使用std::is_same会好很多
  • 请发布确切的错误消息并显示您如何调用模板。快速浏览一下,template &lt;class Arg&gt; 通常指定为template &lt;typename Arg&gt;,因为doublefloat 不是类。
  • 谢谢,我已经修好了
  • @KenY-N 在这种情况下,classtypename 在当前标准中被视为相同,因此您的建议不适用。 class 很乐意被推导出为原始类型。

标签: c++


【解决方案1】:

如果不需要 C++17 代码,可以使用重载

tuple<int, double> foo(int a) {
    return {a, 0.0};
}

tuple<int, double> foo(double a) {
    return {0, a};
}

template<typename T>
tuple<int, double> foo(T) {
    return {0, 0.0};
}

如果您需要 C++17 代码:

template<typename T>
tuple<int, double> foo([[maybe_unused]] T a) {
    if constexpr (std::is_same_v<int, T>)
        return {a, 0.0};

    else if constexpr (std::is_same_v<double, T>)
        return {0, a};

    else
        return {0, 0.0};
}

【讨论】:

  • 在您的C++17 版本中,您需要在else if 之后添加一个constexpr
  • 你确定吗?此代码使用 clang 和 gcc 和 msvc 编译
  • 你试过在 main 中调用 foo("const char* arg") 吗?
  • 确实不应该。请参阅my question and the accepted answer 了解原因。使用const char* 作为参数,return {0, a} 将被编译(因为它not constexpr)并且即使std::is_same_v&lt;double, T&gt; 将产生falsereturn 语句也必须是编译。您是如何编译代码的?确切的代码是什么?
  • 好的,我使用了 constexpr 函数。谢谢,我修好了;)。
【解决方案2】:

最简单的解决方案是只使用 3 个单独的重载:

tuple<int, double> calc(int arg)
{
  return make_tuple(arg, 0.);
}

tuple<int, double> calc(double arg)
{
  return make_tuple(0, arg);
}

template < typename T >
tuple<int, double> calc(T arg)
{
  return make_tuple(0, 0.);
}

您也可以使用模板特化:

template < typename T >
tuple<int, double> calc(T arg)
{
  return make_tuple(0, 0.);
}

template <>
tuple<int, double> calc< int >(int arg)
{
  return make_tuple(arg, 0.);
}

template <>
tuple<int, double> calc< double >(double arg)
{
  return make_tuple(0, arg);
}

【讨论】:

  • 您的第一个解决方案似乎是我的答案的一种复制和过去
  • @AntoineMorrier 没有复制粘贴。任何有经验的 C++ 程序员都可以编写。
  • 复制和过去是表达我想说的话的错误方式^^,我只是说答案已经给出;)
  • @AntoineMorrier 是的,它不是复制粘贴,我在你发布答案之前就开始写了
  • 好的,我知道了,只是说得很不好,对不起^^
猜你喜欢
  • 2023-03-08
  • 2014-09-20
  • 2015-01-05
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多