假设我们有一个(虚构的)类模板C<T>
,其中带有条件明确的默认构造函数。当且仅当std::is_same_v<T, int>
时,默认构造函数才应为显式。
A search on "[c++] conditionally explicit"返回以下结果:Constructor conditionally marked explicit。
可接受的答案给出了一个例子:
struct S { template <typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = false > S(T) {} template <typename T, typename std::enable_if<!std::is_integral<T>::value, bool>::type = false> explicit S(T) {} };
稍稍修改示例即可使用类似于std::enable_if
的方法来实现此实现:
template <class T>
class C {
public:
template <std::enable_if_t<std::is_same_v<T, int>, int> = 0>
C() {}
template <std::enable_if_t<!std::is_same_v<T, int>, int> = 0>
explicit C() {}
};
不幸的是,它甚至无法编译:demo
prog.cc: In instantiation of 'class C<int>':
prog.cc:15:10: required from here
prog.cc:10:12: error: no type named 'type' in 'struct std::enable_if<false, int>'
10 | explicit C() {}
| ^
prog.cc: In instantiation of 'class C<double>':
prog.cc:18:13: required from here
prog.cc:7:3: error: no type named 'type' in 'struct std::enable_if<false, int>'
7 | C() {}
| ^
该问题似乎是由于省略了构造函数的模板参数,从而禁用了SFINAE造成的。
如果可能的话,我想避免对课程进行专门化。
答案 0 :(得分:2)
- 什么是可能的实现方式?
您尝试过
template <class T>
class C {
public: // VVVVVVVVVVVVVV .................................V U here, not T
template <typename U = T, std::enable_if_t<std::is_same_v<U, int>, int> = 0>
C() {}
template <typename U = T, std::enable_if_t<!std::is_same_v<U, int>, int> = 0>
explicit C() {}
};
?
- 为什么不编译?
问题在于SFINAE通过类方法使用方法本身的模板参数。
在原始工作代码中:
template <typename T,
typename std::enable_if<std::is_integral<T>::value, bool>::type = false >
S(T) {}
其中T
是特定于构造函数的模板参数(从单个参数推导得出)。
相反,在失败的代码中,
template <std::enable_if_t<std::is_same_v<T, int>, int> = 0>
C() {}
构造函数正在评估类(T
)的模板参数,而不是方法的模板参数。
使用技巧typename U = T
,您可以在T
中转换类的模板参数U
,该方法是方法的模板参数(在您的情况下为构造函数,但也可以与其他方法),因此std::enable_if_t
(通过U
进行测试)能够启用/禁用构造函数。