我怀疑我不能这样做,但我想先在这里问明智社区。 p>
我想检查一小撮(比如十个,但可能只有两三个)变量是否等于相同的特定值。 e.g。
if (X == 3 || Y == 3 || Z == 3 || W == 3) ...
在Python中,我习惯于简单地做if 3 in (X, Y, Z, W):
,但无论如何。
无论如何,我想知道是否有可能将它抽象为变量宏,例如EQU_ANY(3, X, Y, Z, W)
,而不是编写一堆EQU_ANYX
宏,其中X是args的数量。
答案 0 :(得分:4)
[使用宏的解决方案结束了,因为它相当可怕而且令人讨厌。]
如果你不介意制作副本,使用std::find
:
std::array<int, 4> values = { X, Y, Z, W };
if (std::find(values.begin(), values.end(), 3) != values.end()) { }
将这一行包装成一个函数通常很好:
template <typename Container, typename Value>
bool contains(const Container& c, const Value& v)
{
return std::find(c.begin(), c.end(), v) != c.end();
}
用作:
std::array<int, 4> values = { X, Y, Z, W };
if (contains(values, 3)) { }
在C ++ 0x中,您可以使用初始化列表而不是创建临时数组:
if (contains({ X, Y, Z, W }, 3)) { }
(这适用于gcc 4.5+;我还不知道还有其他任何支持此C ++ 0x功能的编译器。)
如果你真的想避免复制对象(例如,如果它们很大或复制成本很高),你可以使用相同功能的间接版本:
#include <boost/iterator/indirect_iterator.hpp>
template <typename Container, typename Value>
bool indirect_contains(const Container& c, const Value& v)
{
return std::find(boost::make_indirect_iterator(c.begin()),
boost::make_indirect_iterator(c.end()),
v)
!= boost::make_indirect_iterator(c.end());
}
用作:
std::array<int*, 4> values = { &X, &Y, &Z, &W };
if (indirect_contains(values, 3)) { }
或者,使用C ++ 0x初始化列表:
if (indirect_contains({ &X, &Y, &Z, &W }, 3)) { }
由于Jonathan Leffler提到了Boost.Preprocessor,这就是解决方案的样子:
#include <boost/preprocessor.hpp>
#define SEQUENCE_CONTAINS_IMPL(r, data, i, elem) \
BOOST_PP_IIF(BOOST_PP_EQUAL(i, 0), BOOST_PP_EMPTY(), ||) \
((elem) == (data))
#define SEQUENCE_CONTAINS(elements, value) \
(BOOST_PP_SEQ_FOR_EACH_I(SEQUENCE_CONTAINS_IMPL, value, elements))
用作:
if (SEQUENCE_CONTAINS((X)(Y)(Z)(W), 3)) { }
扩展为:
if ((((X) == (3)) ||
((Y) == (3)) ||
((Z) == (3)) ||
((W) == (3)))) { }
(这很丑陋而且很可怕;我不会在我的代码中使用它,但是如果你真的担心要制作两三个值的副本,你可能不希望有机会进行函数调用无论是。)
答案 1 :(得分:1)
尝试使用switch语句。您可以为多个条件指定相同的行为,如下所示:
switch (n) {
case 1:
case 2:
case 3:
// Do something
break;
}
这相当于
if (x == 1 || x == 2 || x == 3)
// Do something
这是最干净的方法。你或许可以编写一个可变开关宏(或者能完成类似事情的东西),但请为你身边的每个人做...不要:P
答案 2 :(得分:1)
由于您还使用C标记了您的问题,因此这是一个仅适用于C99和可变参数宏的答案,C ++没有。使用P99执行语句展开
#define TESTIT(WHAT, X, I) X == WHAT
#define TEST_MORE(WHAT, ...) P99_FOR(WHAT, P99_NARG(__VA_ARGS__), P00_OR, TESTIT, __VA_ARGS__)
这里
TEST_MORE(A, b, c, d, e, f)
TEST_MORE(3, b, c, d, e, f)
然后
((((((((b == A) || (c == A))) || (d == A))) || (e == A))) || (f == A))
((((((((b == 3) || (c == 3))) || (d == 3))) || (e == 3))) || (f == 3))
与boost相比,这样做的优势在于对TEST_MORE
的最终调用简单易读。
答案 3 :(得分:0)
最有可能使用Boost的boost::preprocessor包中的工具(可以与C和C ++一起使用)来完成。