这些类之间的区别是什么?具体来说,这些成员函数都是enable_if
。
/// Alias of std::enable_if...
template <bool B, typename T = void>
using Enable_if = typename std::enable_if<B, T>::type;
template<typename T, std::size_t N>
class A {
...
template <std::size_t NN = N,
typename = Enable_if<NN == 2>>
Some_Return_Type
method(param1, param2)
{}
template <std::size_t NN = N,
typename = Enable_if<NN == 1>>
Some_Return_Type
method(param1)
{}
};
template<typename T, std::size_t N>
class B {
...
Enable_if<N == 2, Some_Return_Type>
method(param1, param2)
{}
Enable_if<N == 1, Some_Return_Type>
method(param1)
{}
};
在下面的例子中使用enable_if
的正确方法是什么:
- 至少有两个方法,它们的参数不同,并且它们具有相同的名称,但其中一个必须是“活动的”(如果
N == 1
其中一个,如果N == 2
另一个)。 - 只有一个方法在
N == 0
情况下处于活动状态,在其他情况下不处于活动状态。
我想得到的东西像:
Obj<int, 2> obj2;
Obj<int, 0> obj0;
Obj<int, 1> obj1;
如果我在IDE中编写obj0.
,它应该只显示以下方法:
N == 0
;- 对于
obj1.
,仅N == 1
- ...
1条答案
按热度按时间ojsjcaue1#
请注意,
enable_if
旨在触发SFINAE:如果模板参数替换在其 immediate 上下文中失败,则不是编译错误。这就是在
class A
中发生的事情:当用户调用a.method(...)
时,编译器尝试示例化成员函数模板method
,用常量替换NN
参数,这可能会失败。然而,在
B::method
的情况下,“坏”替换发生在类模板B
示例化期间,当编译器替换N
时。失败发生在远离参数的直接上下文的地方,在本例中是template<typename T, std::size_t N> class B
。这就是为什么在第二种情况下,你会得到一个编译错误,而不是SFINAE。
因此,要根据 class template 参数启用/禁用成员函数,请使用第一种方法,根据需要组合条件。例如:
UPDATE:enable_if的工作原理。大致上,可以这样实现它:
请注意,如果第一个参数是
false
,则enable_if
没有内部type
,因此enable_if<false, int>::type
将是病态的。这就是触发SFINAE。