【发布时间】:2021-11-10 05:13:08
【问题描述】:
我正在尝试为自定义模板类创建一个加法运算符,其中允许第一个参数是我的类的实例或基本数字类型。我的操作符的定义类似于下面的示例代码:
#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
: main.cpp:18:38: 需要来自‘struct MyCommonType ’
main.cpp:31:39: 替换‘templateMyTemplateStruct ::type> operator+(T, const MyTemplateStruct&) [with T = MyTemplateStruct; U = 双]'
main.cpp:40:13:从这里需要 /usr/include/c++/7/type_traits:2484:61: error: no type named ‘type’ in ‘struct std::common_type, double>’
如果我在运算符定义中直接使用std::common_type_t,而不是使用我的包装器模板MyCommonTypeT,那么SFINAE 会按我的预期工作并且没有错误。当我必须将对 std::common_type 的调用包装在另一个模板中时,如何编译上述代码?
【问题讨论】:
-
查看this answer,看来我可能需要添加一个取值
true_type/false_type的模板,具体取决于我的模板是否接受提供的模板参数。然后,声明我的结构采用默认参数指示是否支持类型 T/U,并且仅在支持时提供typedef。看起来有点笨拙,但它可能会起作用。