【问题标题】:Type conversion in template模板中的类型转换
【发布时间】:2018-10-26 17:08:28
【问题描述】:

我正在使用一个模板函数和一个非模板函数。代码如下

#include <iostream>
using namespace std;

int maxOfTwo1(int a,int b)
{
    return a>b?a:b;
}
template<class T>
T maxOfTwo(T a,T b)
{
    return a>b?a:b;
}
int main()
{
    cout<<maxOfTwo1(3,6.3);//works fine
    cout<<maxOfTwo(3,6.3);//gives error
}

在第一个函数中,6.3 正在转换为 6,但谁能解释为什么它也不会在第二个函数中发生?第二个功能也一样,只是有模板。

【问题讨论】:

    标签: c++ c++11 templates type-conversion type-deduction


    【解决方案1】:

    演绎冲突。

    给定

    template<class T>
    T maxOfTwo(T a,T b)
    {
        return a>b?a:b;
    }
    

    如果调用maxOfTwo(3,6.3),第一个值为int;第二个是float

    编译器必须推导出一个T类型,不知道是选择int还是float

    maxOfTwo1() 的情况不同,因为参数的类型固定为int,编译器只需将float 值转换为int 值。

    如果至少可以使用 C++14,则可以使用两个模板类型和一个返回的auto 类型来解决

    template <typename T1, typename T2>
    auto maxOfTwo (T1 a, T2 b)
     { return a>b?a:b; }
    

    在 C++11 中更冗长,更不优雅

    template <typename T1, typename T2>
    auto maxOfTwo (T1 a, T2 b) -> decltype( a>b ? a : b )
     { return a>b?a:b; }
    

    或者你可以使用std::common_type(由 Yakk 建议)

    template <typename T1, typename T2>
    typename std::common_type<T1, T2>::type maxOfTwo (T1 a, T2 b)
     { return a>b?a:b; }
    

    否则你可以显式调用函数的正确类型

    maxOfTwo<int>(3, 6.3);
    

    【讨论】:

    • std::common_type 可以在 C++11 中使用。在某些情况下,它还会扩展 ?:,例如 std::chrono 类型。
    • @Yakk-AdamNevraumont - 你是对的;我在想可以从 C++14 获得;谢谢!
    【解决方案2】:

    在您的第一种情况下,参数的类型是已知的 (int),并且参数被转换为格式正确的该类型 (int)。

    在您的第二种情况下,编译器必须推导出 T 但它以相互冲突的推论结束,因此它失败了。

    我们可以从[temp.deduct.type]p2 看到这一点(强调我的):

    在某些情况下,使用单个类型 P 和 A 的集合进行推导,在其他情况下,将有一组相应的类型 P 和 A。类型推导是针对每个 P/A 对独立完成的,并且然后组合推导出的模板参数值。如果不能对任何 P/A 对进行类型推导,或者如果对任何 P/A 对的推导导致多于一组可能的推导值,或者如果不同的对产生不同的推导值,或者如果有模板参数既没有推导也没有明确指定,模板参数推导失败。

    PA的定义见[temp.deduct.call]p1:

    模板实参推导是通过将每个函数模板形参类型(称为 P)与调用的相应实参类型(称为 A)进行比较来完成的,如下所述。如果从 P 中删除引用和 cv 限定符给出一些 P' 的 std::initializer_list 并且参数是初始化列表 ([dcl.init.list]),则对初始化列表的每个元素执行推导,取 P ' 作为函数模板参数类型,初始化元素作为其参数。否则,初始化列表参数会导致参数被视为非推导上下文 ([temp.deduct.type])。

    max66 给出了一些可能的解决方案,即使用不同的模板参数结合common_type

    【讨论】:

      猜你喜欢
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多