c++ - 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
在另一个模板中时,如何编译上述代码?
解决方案
您需要使MyCommonTypeT<T, U>
(ie ) 本身无效,在 中声明时仅无效是MyCommonType<T, U>::type
不够的。例如你可以specialize ,当被指定为模板参数时,不被声明。std::common_type_t<T, U>
type
MyCommonType
MyCommonType
MyTemplateStruct
type
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>> {};
推荐阅读
- python - 链接响应是 401,但它在前一段时间工作,然后工作 python
- javascript - Firebase 模拟器对本地 FireStore 的请求不成功
- reactjs - 什么是防止浏览器缓存文件反应的最佳解决方案
- git - 如何为 git pull 合并消息提供评论
- terraform - 用于检索键值的 Terraform 过滤器
- c++11 - 使用 C++11 模板生成算法的多个版本
- python - 无法在 Python 中使用 xpath 定位元素
- macos - Mac 上的 Kafka 在启动控制台使用者时没有对节点 -1 的正在进行的请求
- jquery - 背景位置 css 不使用变量
- struct - 如何将约束添加到结构的字段以进行实例化?