[使用宏的解決方案是在年底,因爲它是相當可怕的,令人討厭的。]
如果你不介意的副本製成,它可能是清潔劑使用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)) { }
由於喬納森·萊弗勒提到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)))) { }
(這是醜陋和可怕的;我不會在我的代碼中使用它,但是如果您真的擔心正在創建的兩個或三個值的副本,您可能不希望有機會進行函數調用。)
不,宏是錯誤的工具 - 無法遍歷宏中的參數。 –
謝謝吉姆,那就是我想知道的。 (啊,如果只有我有Lisp宏..) – Kevin
嗯,事實證明,我錯了 - boost :: preprocessor包有真正迂迴的方式來實現這個多達256個參數。請看喬納森和詹姆斯的答案(你真的應該接受後者)。 –