motivation: I would like to create a utility class so that instead of having to write:
if( someVal == val1 || someVal == val2 || someVal == val3 )
I could instead write:
if( is(someVal).in(val1, val2, val3) )
which is much closer to the mathematical 'a is an element of (b,c,d)' and also would save on a lot of typing when the variable name 'someVal' is long.
Here is the code I have so far (for 2 and 3 values):
template<class T>
class is {
private:
T t_;
public:
is(T t) : t_(t) { }
bool in(const T& v1, const T& v2) {
return t_ == v1 || t_ == v2;
}
bool in(const T& v1, const T& v2, const T& v3) {
return t_ == v1 || t_ == v2 || t_ == v3;
}
};
However it fails to compile if I write:
is(1).in(3,4,5);
instead I have to write
is<int>(1).in(3,4,5);
Which isn't too bad, but it would be better if somehow the compiler could figure out that the type is int
with out me having to explicitly specify it.
Is there anyway to do this or I am stuck with specifying it explicitly?
If you want to keep this syntax, you can use a helper function like :
template<class T>
class is_op {
private:
T t_;
public:
is_op(T t) : t_(t) { }
bool in(const T& v1, const T& v2) {
return t_ == v1 || t_ == v2;
}
bool in(const T& v1, const T& v2, const T& v3) {
return t_ == v1 || t_ == v2 || t_ == v3;
}
};
template< class U >
inline is_op<U> is( U const& v )
{
return is_op<U>( v );
}
int main(int argc, char* argv[])
{
is( 1 ).in( 1 , 2 , 4 );
}
The problem is quite amusing, it's true that boolean conditions can get hairy.
I myself tend to prefer writing special functions though, because the meaning here is hard to convey. What does:
if (someVal == val1 || someVal == val2 || someVal == val3)
means ?
Is
if ( is(someval).in(val1, val2, val3) )
// or
if ( is(someval).in(val1)(val2)(val3) ) // implements short-circuiting
// and removes arity issue
// using a proxy object
better?
I think it would be easier to read with:
bool isToBeLogged(const Foo& foo)
{
// Either
static std::set<Foo> ValuesToLog = /* some boost assign magic or whatever */;
return ValuesToLog.find(foo) != ValuesToLog.end();
// Or
return foo == val1 || foo == val2 || foo == val3;
}
if (isToBeLogged(someVal))
I guess it's a matter of style.
The advantages of the second method including:
Inconvients ? I guess it's more typing... oh well :p
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With