c++ - 在 pre C++11,C++11,14和 17,C++ 如何简化复杂的SFINAE语法?

  显示原文与译文双语对照的内容
135 3

这个问题是由激发的。我想知道在给定的标准中,什么是最好的方法来简化它。我知道和个人使用过的一个,因为C++14是宏 REQUIRES(x):

定义:

template<long N>
struct requires_enum
{
 enum class type
 {
 none,
 all
 };
};
#define REQUIRES(...) requires_enum<__LINE__>::type = 
 requires_enum<__LINE__>::type::none, 
 bool PrivateBool = true, 
 typename std::enable_if<PrivateBool && (__VA_ARGS__), int>::type = 0

即使对于非模板函数调用,也可以使用:

template<REQUIRES(sizeof(int)==4)>
int fun() {return 0;}
int main()
{ 
 fun();//only if sizeof(int)==4
}

原来的REQUIRES 我使用来自这个邮局。

还有什么好的技术?

有些SFINAE需要一些或者长时间来理解刚刚启动SFINAE冒险的读者:

Pre-C++11 SFINAE示例( 源代码):

template <typename T>
struct has_typedef_foobar {
//Types"yes" and"no" are guaranteed to have different sizes,
//specifically sizeof(yes) == 1 and sizeof(no) == 2.
 typedef char yes[1];
 typedef char no[2];
 template <typename C>
 static yes& test(typename C::foobar*);
 template <typename>
 static no& test(...);
//If the"sizeof" of the result of calling test<T>(nullptr) is equal to sizeof(yes),
//the first overload worked and T has a nested type named foobar.
 static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};
时间:原作者:0个回答

68 3

如果使用 C++11 ( 示例代码包含 std::enable_if,所以我想这就是) 或者连续修订,我将在这种情况下使用 static_assert:

int fun() {
 static_assert(sizeof(int)==4,"!");
 return 0;
}
int main() {
 fun();
}

你没有一组函数,从这个集合中选择一个工作。
,this替换失败总是一个错误,而不是替代失败is不是一个错误
你需要一个编译时间触发器,一个 static_assert 用温和的错误消息来做。

当然,阅读起来也比复杂的sfinae表达式更容易阅读 !

如果要在两个函数之间选择并且不想使用模板机器或者宏,请不要忘记重载是语言( 。pre-C++11工作示例)的一部分:

#include <iostream>
template<bool> struct tag {};
int fun(tag<true>) { return 0; } 
int fun(tag<false>) { return 1; }
int fun() { return fun(tag<sizeof(int) == 4>()); }
int main() {
 std::cout <<fun() <<std::endl;
}

在函数多于两个的情况下,可以很容易地扩展到以下情况:

#include <iostream>
template<int> struct tag {};
int fun(tag<0>) { return 0; }
int fun(tag<1>) { return 1; }
int fun(tag<2>) { return 2; }
int fun(bool b) {
 if(b) { return fun(tag<0>()); }
 else { return fun(tag<(sizeof(int) == 4)? 1 : 2>());
}
int main() {
 std::cout <<fun(false) <<std::endl;
}

你可以将这些函数放入一个匿名名称空间中,并离开它们。

当然,请注意,在pre-C++11中我们被授权编写 enable_if 和它的他从 type_traits 到自己的事物。
举例来说,

template<bool b, typename = void>
struct enable_if { };
template<typename T>
struct enable_if<true, T> { typedef T type; };
原作者:
...