如何对继承构造函数执行正确的SFINAE
How do I do proper SFINAE on inheriting constructors?
我正在尝试对构造函数执行SFINAE。我想为整数启用一个重载,为其他所有重载启用一个。我知道我可以只做一个base(int)
和base(T)
构造函数,但我想用这种方式来做。
template <class T>
struct base
{
template <class T1 = T>
base(T1, typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr) {}
template <class T1 = T>
base(T1, typename std::enable_if<!std::is_same<T1, int>::value>::type* = nullptr) {}
};
然后,我创建了一个继承构造函数的主Base
类:
template <class T>
struct Base : base<T>
{
using base<T>::base;
};
但当我用任何T
实例化Base
时,我会得到以下错误:
source_file.cpp:21:15: error: call to deleted constructor of 'Base<int>'
Base<int> v(4);
^ ~
source_file.cpp:16:25: note: deleted constructor was inherited here
using base<T>::base;
^
source_file.cpp:7:5: note: constructor cannot be inherited
base(T1, typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr) {}
^
当我直接实例化base
时,它可以毫无问题地工作。为什么我在做SFINAE时不能继承构造函数?如果没有第二个构造函数重载,一切都可以正常工作。
您可以在示例程序中完全避免这个问题,方法是在base
中只定义泛型构造函数,并为base<int>
(DEMO)提供专门化:
template <class T>
struct base
{
base(T) { std::cout << "generic constructorn"; }
};
template <>
base<int>::base(int) { std::cout << "int specializationn"; }
或者使用标签调度而不是SFINAE(DEMO):
template <class T>
class base
{
base(std::true_type, int) { std::cout << "int specializationn"; }
base(std::false_type, T) { std::cout << "generic constructorn"; }
public:
base(T t) : base(std::is_same<int, T>{}, std::move(t)) {}
};
与构造函数的参数列表不同,整个模板参数列表总是继承的,包括默认的模板参数。把SFINAE放在那里:
template <class T>
struct base
{
template <class T1 = T,
typename std::enable_if<std::is_same<T1, int>::value>::type* = nullptr>
base(T1) {}
template <class T1 = T,
typename std::enable_if<!std::is_same<T1, int>::value>::type* = nullptr>
base(T1) {}
};
这在Clang和GCC中工作,在-std=c++11
和-std=c++1z
模式中工作。(仅测试了最新版本,分别为3.6和5.1。)
相关文章:
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- C++,系统无法执行指定的程序
- 使用C++中的模板和运算符重载执行矩阵运算
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 执行函数时导致崩溃的变量
- 无论条件是否为true,if总是在c++中执行
- 为什么使用SFINAE而不是函数重载
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 在C++中对T*类型执行std::move的意外行为
- 如何使用模板函数的函数签名进行SFINAE
- 数据成员SFINAE的C++17测试:gcc vs clang
- 使用在用于SFINAE的void_t中具有参数的方法
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如何在没有信号的情况下从C++执行QML插槽
- 如何确认我的constexpr表达式实际上已经在编译时执行
- C++17中的并行执行策略
- QML按钮点击功能执行顺序
- 程序在执行程序的其余部分之前退出
- 在执行 SFINAE 时访问模板派生类 (CRTP) 的静态函数时类型不完整
- 如何对继承构造函数执行正确的SFINAE