首页 > 解决方案 > C++ 嵌套 SFINAE 模板产生编译错误

问题描述

我正在尝试为自定义模板类创建一个加法运算符,其中第一个参数可以是我的类的实例或基本数字类型。我的操作员的定义类似于下面的示例代码:

#include <type_traits>

template<typename T>
struct MyTemplateStruct {
    T val;
};

template<typename T, typename U>
struct MyCommonType {
    typedef std::common_type_t<T, U> type;
};
template<typename T, typename U>
using MyCommonTypeT = typename MyCommonType<T, U>::type;

template<typename T, typename U>
MyTemplateStruct<MyCommonTypeT<T, U>> operator +(
    MyTemplateStruct<T> const& a, MyTemplateStruct<U> const& b)
{
    return { a.val + b.val };
}

template<typename T, typename U>
MyTemplateStruct<MyCommonTypeT<T, U>> operator +(
    T const a, MyTemplateStruct<U> const& b)
{
    return { a + b.val };
}

int main()
{
    MyTemplateStruct<double> a{ 0 }, b{ 0 };
    a = a + b;

    return 0;
}

我的期望是,由于 SFINAE,尝试实例化第二个运算符定义导致的编译错误T = MyTemplateStruct<double>, U = double只会将该模板从潜在匹配列表中排除。但是,当我编译时,我收到以下错误:

/usr/include/c++/7/type_traits: 使用 common_type_t = typename std::common_type::type [with _Tp = {MyTemplateStruct, double}] 替换 'template<class ... _Tp>:
main.cpp: 18:38: 'struct MyCommonType<MyTemplateStruct, double>'<br> main.cpp:31:39: 需要替换'template<class T, class U> MyTemplateStruct<typename MyCommonType<T, U>::类型> operator+(T, const MyTemplateStruct&) [with T = MyTemplateStruct; U = double]'<br> main.cpp:40:13: 从这里需要 /usr/include/c++/7/type_traits:2484:61: 错误: 'struct std::common_type 中没有名为 'type' 的类型,双>'</p>

如果我直接std::common_type_t在运算符定义中使用,而不是使用我的包装器模板MyCommonTypeT,那么 SFINAE 会按我的预期工作并且没有错误。当我必须将调用包装std::common_type在另一个模板中时,如何编译上述代码?

标签: c++templatessfinae

解决方案


您需要使MyCommonTypeT<T, U>(ie ) 本身无效,在 中声明时仅无效是MyCommonType<T, U>::type不够的。例如你可以specialize ,当被指定为模板参数时,不被声明。std::common_type_t<T, U>typeMyCommonTypeMyCommonTypeMyTemplateStructtype

template<typename T, typename U>
struct MyCommonType {
    typedef std::common_type_t<T, U> type;
};
template<typename T, typename U>
struct MyCommonType<MyTemplateStruct<T>, U> {};
template<typename T, typename U>
struct MyCommonType<T, MyTemplateStruct<U>> {};

居住


推荐阅读