【发布时间】:2013-01-14 01:03:53
【问题描述】:
Scott Meyers 发布了他的下一本书 EC++11 的 content and status。
他写道,书中的一项内容可能是“在函数签名中避免std::enable_if”。
std::enable_if 可用作函数参数、返回类型或类模板或函数模板参数,以有条件地从重载决议中删除函数或类。
在this question 中显示了所有三个解决方案。
作为函数参数:
template<typename T>
struct Check1
{
template<typename U = T>
U read(typename std::enable_if<
std::is_same<U, int>::value >::type* = 0) { return 42; }
template<typename U = T>
U read(typename std::enable_if<
std::is_same<U, double>::value >::type* = 0) { return 3.14; }
};
作为模板参数:
template<typename T>
struct Check2
{
template<typename U = T, typename std::enable_if<
std::is_same<U, int>::value, int>::type = 0>
U read() { return 42; }
template<typename U = T, typename std::enable_if<
std::is_same<U, double>::value, int>::type = 0>
U read() { return 3.14; }
};
作为返回类型:
template<typename T>
struct Check3
{
template<typename U = T>
typename std::enable_if<std::is_same<U, int>::value, U>::type read() {
return 42;
}
template<typename U = T>
typename std::enable_if<std::is_same<U, double>::value, U>::type read() {
return 3.14;
}
};
- 应该首选哪种解决方案,为什么要避免使用其他解决方案?
- 在哪些情况下“在函数签名中避免
std::enable_if” 涉及用作返回类型(它不是普通函数签名的一部分,而是模板特化的一部分)? - 成员函数模板和非成员函数模板有什么区别吗?
【问题讨论】:
-
因为重载通常也一样好。如果有的话,委托给使用(专门的)类模板的实现。
-
好吧,只是主观上我不得不说,虽然经常非常有用,但我不喜欢
std::enable_if弄乱我的函数签名(尤其是丑陋的附加nullptr函数参数版本),因为它总是看起来它是什么,一个奇怪的黑客(static if可能会做得更漂亮和干净)使用模板黑魔法来利用有趣的语言功能。这就是为什么我尽可能喜欢标签调度(嗯,你仍然有额外的奇怪参数,但不是在公共接口中,而且更不用说丑陋和神秘)。 -
我想问一下
=0中的typename std::enable_if<std::is_same<U, int>::value, int>::type = 0是做什么的?我找不到正确的资源来理解它。我知道=0之前的第一部分有一个成员类型int如果U和int相同。非常感谢! -
@astroboyrx 有趣的是,我只是想发表评论指出这一点。基本上,=0 表示这是一个默认的非类型模板参数。这样做是因为默认的类型模板参数不是签名的一部分,所以你不能重载它们。
-
赞成这个问题,因为它有所有使用 enable_if 的方法! (;
标签: c++ templates c++11 sfinae enable-if