检查值的辅助函数是它的任何参数
helper function to check a value is any of its parameters
我需要使用辅助函数检查类型 T 的值是否是它的任何参数。
例如,使用类似下面的代码
enum class my_enum{k1, k2, k3, k4, k5};
auto v{my_enum::k1};
if (is_any_of(v, my_enum::k1, my_enum::k4, my_enum::k5)) {
}
而不是使用 if (v == my_enum::k1 || v == my_enum::k4 || v== my_enum::k5) {}
或使用 switch-case
。
如何在 C++11 中实现可变函数 bool is_any_of()
?
如何使用 C++17 倍表达式使实现变得更简单?
这将在 C++11 中工作,并且只要所有类型都可以相互比较就可以做你想做的事。
template<typename T, typename R>
bool is_any_of(T t, R r)
{
return t == r;
}
template<typename T, typename R, typename... ARGS>
bool is_any_of(T t, R r, ARGS... args)
{
if (t == r)
{
return true;
}
else
{
return is_any_of(t, args...);
}
}
这更加紧凑,可以在 C++17 中使用
template<typename T, typename... ARGS>
bool is_any_of(T t, ARGS... args)
{
return ((t == args) || ...);
}
对于非递归 C++11 替代方案:
template <typename T, typename... Ts>
bool is_any_of (T t, Ts&&... ts) {
std::initializer_list<bool> eq { (t == ts)... };
return std::any_of(eq.begin(), eq.end(), [](bool i){ return i; });
}
但正如已经回答的那样,折叠表达式 return ((t == ts) || ...);
更紧凑、更富有表现力且可优化。
You've already received good template based solutions. I had authored one myself, but it duplicated another answer. So, this answer is different, but it also does not use templates. Instead, it uses a variadic macro.
如果您需要真正的短路行为,则需要展开完整的表达式。否则,如果参数有副作用,将它们传递给一个函数将触发所有这些。作为一个人为的例子,
template <typename T>
const T & x(const T &v) {
std::cout << __func__ << ": " << v << '\n';
return v;
}
//...
if (is_any_of(2, x(1), x(2), x(3))) {
//...
}
当在 x(2)
上检测到匹配时,短路实现将避免调用 x(3)
。但是,这需要 is_any_if(...)
扩展为:
if ((2 == x(1)) || (2 == x(2)) || (2 == x(3))) {
//...
您可以使用宏来完成此扩展。下面是一种可能的实现,最多可以使用 9 个参数进行测试。
#define is_any_of(...) \
(V_(V_(is_any_of_X(__VA_ARGS__,A,9,8,7,6,5,4,3,2,_))(__VA_ARGS__)))
#define is_any_of_X(_A,_9,_8,_7,_6,_5,_4,_3,_2,_1,X,...) is_any_of_##X
#define is_any_of_A(V, X, ...) ((X) == (V)) || is_any_of_9(V, __VA_ARGS__)
#define is_any_of_9(V, X, ...) ((X) == (V)) || is_any_of_8(V, __VA_ARGS__)
#define is_any_of_8(V, X, ...) ((X) == (V)) || is_any_of_7(V, __VA_ARGS__)
#define is_any_of_7(V, X, ...) ((X) == (V)) || is_any_of_6(V, __VA_ARGS__)
#define is_any_of_6(V, X, ...) ((X) == (V)) || is_any_of_5(V, __VA_ARGS__)
#define is_any_of_5(V, X, ...) ((X) == (V)) || is_any_of_4(V, __VA_ARGS__)
#define is_any_of_4(V, X, ...) ((X) == (V)) || is_any_of_3(V, __VA_ARGS__)
#define is_any_of_3(V, X, ...) ((X) == (V)) || is_any_of_2(V, __VA_ARGS__)
#define is_any_of_2(V, X) ((X) == (V))
#define is_any_of_1(...) false
#define is_any_of_0(...) true
#define is_any_of_Y(_1,Y,...) is_any_of_##Y
#define is_any_of__(...) I_(is_any_of_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)
#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,
技术说明here。简而言之,它应用了一个宏参数计数技巧,以及一个可移植的方法来检测单参数情况是否实际上是空参数情况。 (如果你使用的是GCC,可以简化检测。)
我需要使用辅助函数检查类型 T 的值是否是它的任何参数。
例如,使用类似下面的代码
enum class my_enum{k1, k2, k3, k4, k5};
auto v{my_enum::k1};
if (is_any_of(v, my_enum::k1, my_enum::k4, my_enum::k5)) {
}
而不是使用 if (v == my_enum::k1 || v == my_enum::k4 || v== my_enum::k5) {}
或使用 switch-case
。
如何在 C++11 中实现可变函数 bool is_any_of()
?
如何使用 C++17 倍表达式使实现变得更简单?
这将在 C++11 中工作,并且只要所有类型都可以相互比较就可以做你想做的事。
template<typename T, typename R>
bool is_any_of(T t, R r)
{
return t == r;
}
template<typename T, typename R, typename... ARGS>
bool is_any_of(T t, R r, ARGS... args)
{
if (t == r)
{
return true;
}
else
{
return is_any_of(t, args...);
}
}
这更加紧凑,可以在 C++17 中使用
template<typename T, typename... ARGS>
bool is_any_of(T t, ARGS... args)
{
return ((t == args) || ...);
}
对于非递归 C++11 替代方案:
template <typename T, typename... Ts>
bool is_any_of (T t, Ts&&... ts) {
std::initializer_list<bool> eq { (t == ts)... };
return std::any_of(eq.begin(), eq.end(), [](bool i){ return i; });
}
但正如已经回答的那样,折叠表达式 return ((t == ts) || ...);
更紧凑、更富有表现力且可优化。
You've already received good template based solutions. I had authored one myself, but it duplicated another answer. So, this answer is different, but it also does not use templates. Instead, it uses a variadic macro.
如果您需要真正的短路行为,则需要展开完整的表达式。否则,如果参数有副作用,将它们传递给一个函数将触发所有这些。作为一个人为的例子,
template <typename T>
const T & x(const T &v) {
std::cout << __func__ << ": " << v << '\n';
return v;
}
//...
if (is_any_of(2, x(1), x(2), x(3))) {
//...
}
当在 x(2)
上检测到匹配时,短路实现将避免调用 x(3)
。但是,这需要 is_any_if(...)
扩展为:
if ((2 == x(1)) || (2 == x(2)) || (2 == x(3))) {
//...
您可以使用宏来完成此扩展。下面是一种可能的实现,最多可以使用 9 个参数进行测试。
#define is_any_of(...) \
(V_(V_(is_any_of_X(__VA_ARGS__,A,9,8,7,6,5,4,3,2,_))(__VA_ARGS__)))
#define is_any_of_X(_A,_9,_8,_7,_6,_5,_4,_3,_2,_1,X,...) is_any_of_##X
#define is_any_of_A(V, X, ...) ((X) == (V)) || is_any_of_9(V, __VA_ARGS__)
#define is_any_of_9(V, X, ...) ((X) == (V)) || is_any_of_8(V, __VA_ARGS__)
#define is_any_of_8(V, X, ...) ((X) == (V)) || is_any_of_7(V, __VA_ARGS__)
#define is_any_of_7(V, X, ...) ((X) == (V)) || is_any_of_6(V, __VA_ARGS__)
#define is_any_of_6(V, X, ...) ((X) == (V)) || is_any_of_5(V, __VA_ARGS__)
#define is_any_of_5(V, X, ...) ((X) == (V)) || is_any_of_4(V, __VA_ARGS__)
#define is_any_of_4(V, X, ...) ((X) == (V)) || is_any_of_3(V, __VA_ARGS__)
#define is_any_of_3(V, X, ...) ((X) == (V)) || is_any_of_2(V, __VA_ARGS__)
#define is_any_of_2(V, X) ((X) == (V))
#define is_any_of_1(...) false
#define is_any_of_0(...) true
#define is_any_of_Y(_1,Y,...) is_any_of_##Y
#define is_any_of__(...) I_(is_any_of_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)
#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,
技术说明here。简而言之,它应用了一个宏参数计数技巧,以及一个可移植的方法来检测单参数情况是否实际上是空参数情况。 (如果你使用的是GCC,可以简化检测。)