std::enable_if 用于两种不同的方法实现(4 种不同的情况)
Posted
技术标签:
【中文标题】std::enable_if 用于两种不同的方法实现(4 种不同的情况)【英文标题】:std::enable_if for two different methods implementation (4 different cases) 【发布时间】:2018-08-22 08:15:18 【问题描述】:我需要为 const 和非常量类型实现两种不同的方法。我已经设法编写了工作代码,但我不明白为什么它的某些风格可以,而有些则不行。
这是一个简化的例子,我想知道为什么 #1 有效,但 #2 无效,关于 #3 和 #4 也是如此:
#include <iostream>
#include <vector>
template <typename T>
class X
public:
// #1 - works
template<typename B = T, typename std::enable_if<std::is_const<B>::value, int>::type = 0>
void foo() std::cout << "CONST" << std::endl;
template<typename B = T, typename std::enable_if<std::is_const<B>::value == false, int>::type = 0>
void foo() std::cout << "NON-CONST" << std::endl;
// #2 - does not work "no type named 'type' in 'std::__1::enable_if<false, int>'; 'enable_if' cannot be used to disable this declaration"
// template<typename std::enable_if<std::is_const<T>::value, int>::type = 0>
// void foo() std::cout << "CONST" << std::endl;
// template<typename std::enable_if<std::is_const<T>::value == false, int>::type = 0>
// void foo() std::cout << "NON-CONST" << std::endl;
// #3 - works
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value>::type>
// void foo() std::cout << "CONST" << std::endl;
// template<typename B = T, typename std::enable_if<std::is_const<B>::value == false>::type * = nullptr>
// void foo() std::cout << "NON-CONST" << std::endl;
// # 4 - does not work - "class member cannot be redeclared"
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value>::type>
// void foo() std::cout << "CONST" << std::endl;
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value == false>::type>
// void foo() std::cout << "NON-CONST" << std::endl;
;
int main()
X<int> v;
X<const int> vConst;
v.foo();
vConst.foo();
return 0;
即使有更好的方法来解决我的问题,我也真的很想了解为什么 enable_if 像它一样(而不是)在给出的示例中起作用。
【问题讨论】:
只是风格问题,但更喜欢!condition
而不是condition == false
...
@Aconcagua:当然,我通常使用!condition
,但不幸的是模板代码可能非常复杂,以至于condition == false
对我来说更加可见/可读。
Why doesn't SFINAE (enable_if) work for member functions of a class template?的可能重复
或者,可能是更好的重复匹配:***.com/q/6972368/580083
旁注:如果在非模板函数中使用 constexpr 可能更容易解决问题(仅适用于您不知道的情况......)。
【参考方案1】:
#2
不起作用,因为您遇到了严重故障,因为 T
已由班级修复。
所以你真的有
template<typename std::enable_if<true, int>::type = 0> // -> template<int = 0> void foo();
void foo();
template<typename std::enable_if<false, int>::type = 0> // Hard error failure
void foo();
对于#4
,默认模板值/类型不是签名的一部分,因此一旦删除,您就有了
template <typename B, typename> void foo() std::cout << "CONST" << std::endl;
template <typename B, typename> void foo() std::cout << "NON-CONST" << std::endl;
具有多个定义的相同方法:您破坏了 ODR。
对于#3
,它将是:
template<typename B, typename>
void foo();
template<typename B, typename std::enable_if<std::is_const<B>::value == false>::type *>
void foo();
这是不同的。
【讨论】:
也许在#3 处很有趣,可以更清楚地说明差异:if 第二个foo
is 启用,它将到达<typename B, void*>
@Aconcagua: 但是签名 differs 在替换之前,例如 Demo 会产生模棱两可的调用(而不是违反 ODR,正如你的句子所暗示的那样)。
不明白为什么我的评论会暗示违反 ODR,我的意图 是 使不同的签名更加明显......
我的意思是typename <typename T, std::enable_if_t<cond<T>, int>> voif f()
和template <typename T, int> void f()
是2个不同的签名,即使替换后,它们的结果是一样的。
啊,我明白了...被您的强调误导了(“但签名甚至在之前替换之前也不同”会更明显),但有趣的方面... 以上是关于std::enable_if 用于两种不同的方法实现(4 种不同的情况)的主要内容,如果未能解决你的问题,请参考以下文章
SWIG C++/Python 绑定和支持带有 std::enable_if 的条件成员
std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系