A class:
class foo{
public:
int data;
};
Now I want to add a method to this class, to do some comparison, to see if its data is equal to on
The answers using std::initializer_list
are fine, but I want to add one more possible solution which is exactly what you where trying with that C variadic in a type-safe and modern way: Using C++11 variadic templates:
template<typename... NUMBERS>
bool any_equal( const foo& f , NUMBERS&&... numbers )
{
auto unpacked = { numbers... };
return std::find( std::begin( unpacked ) , std::end( unpacked ) , f.data )
!= std::end( unpacked );
};
Of course this only works if all values passed are of the same type. If not the initializer list unpacked
cannot be deduced nor initialized.
Then:
bool equals = any_equal( f , 1,2,3,4,5 );
EDIT: Here is a are_same
metafunction to ensure that all the numbers passed are of the same type:
template<typename HEAD , typename... TAIL>
struct are_same : public and_op<std::is_same<HEAD,TAIL>::value...>
{};
Where and_op
performs n-ary logical and:
template<bool HEAD , bool... TAIL>
struct and_op : public std::integral_constant<bool,HEAD && and_op<TAIL...>::value>
{};
template<>
struct and_op<> : public std::true_type
{};
This makes possible to force the usage of numbers of the same type in a simple way:
template<typename... NUMBERS>
bool any_equal( const foo& f , NUMBERS&&... numbers )
{
static_assert( all_same<NUMBERS...>::value ,
"ERROR: You should use numbers of the same type" );
auto unpacked = { numbers... };
return std::find( std::begin( unpacked ) , std::end( unpacked ) , f.data )
!= std::end( unpacked );
};
If data
is really an integral or enumerated type, you can use a switch
:
switch (data) {
case 1:
case 2:
case 2000:
case 6000:
case /* whatever other values you want */:
act_on_the_group();
break;
default:
act_on_not_the_group();
break;
}
Any optimization is going to depend on properties of the set of numbers being compared to.
If there's a definite upper bound, you can use a std::bitset. Testing membership (that is, indexing into the bitset, which behaves like an array), is O(1), effectively a few fast instructions. This is often the best solution up to limits in the hundreds, although depending on the application millions could be practical.
If data, num1, .. num6 are between 0 and 31, then you can use
int match = ((1<<num1) | (1<<num2) | ... | (1 << num6));
if( ( (1 << data) & match ) != 0 ) ...
If num1 to num6 are constants, the compiler will compute match at compile time.