gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 23:17:51 24 4
gpt4 key购买 nike

这个问题的灵感来自 this answer .我想知道在给定标准中简化它的最佳方法是什么/是什么。自 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

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

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

int main()
{
fun(); //only if sizeof(int)==4
}

我使用的原始REQUIRES来自这个post .

还有哪些好的技巧?


对于刚开始使用 SFINAE 冒险的读者来说,一些 SFINAE 示例需要一些时间或很长时间才能理解:

C++11 之前的 SFINAE 示例(Source):

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);
};

最佳答案

如果您正在使用 C++11(示例代码包含 std::enable_if,所以我猜是这种情况)或后续版本,我会使用 static_assert 在这种情况下:

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

int main() {
fun();
}

您没有一组函数可以从中挑选一个正在工作的。
正如我曾经说过的,这更像是一个替换失败总是一个错误,而不是一个替换失败不是一个错误
你想要的是一个编译时触发器和一个 static_assert 用温和的错误消息来做。

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


如果您想在两个函数之间进行选择并且不想使用模板机制或宏,请不要忘记重载是语言的一部分(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;
}

您可以将这些函数放在匿名命名空间中,然后就可以不用了。


当然,还请注意,在 C++11 之前,我们被授权为自己编写 enable_iftype_traits 中的所有其他内容。
举个例子:

template<bool b, typename = void>
struct enable_if { };

template<typename T>
struct enable_if<true, T> { typedef T type; };

关于c++ - 如何在 pre-C++11、C++11、14 和 17 中简化复杂的 SFINAE 语法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39727409/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com