Вы уже получили хорошие решения на основе шаблонов. Я сам написал один, но он дублировал другой ответ. Таким образом, этот ответ отличается, но он также не использует шаблоны. Вместо этого он использует макрос variadi c.
Если вам нужно истинное поведение при коротком замыкании, вам нужно будет развернуть полное выражение. В противном случае, если параметры имеют побочные эффекты, передача их в функцию вызовет их все. В качестве надуманного примера,
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(3)
при обнаружении совпадения на x(2)
. Но для этого нужно, чтобы is_any_if(...)
расширилось до:
if ((2 == x(1)) || (2 == x(2)) || (2 == x(3))) {
//...
Вы можете использовать макрос для выполнения sh этого расширения. Ниже приведена одна из возможных реализаций, которая может принимать до 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_() _,
Методика объяснена здесь . Вкратце, он применяет трюк подсчета аргументов макроса, а также переносимый метод для определения, является ли регистр с одним аргументом регистром пустого аргумента. (Если вы используете G CC, обнаружение может быть упрощено.)