C ++ operator "no operator"?

I would like to emulate a Python statement in

in C ++ (11) using immediately the values ​​as you can in Python. For example:

if x in (1, 2, 3): ...

      

In C ++ 11, it seems like I'm close to being able to do this:

if (IsIn(x, { 1, 2, 3 }))
    {
    }


template<typename Val, Container cont>
bool IsIn(Val const &val, Container const &cont)
    {
    return boost::find(cont, val) != cont.end();
    }

      

But (in g ++ - 4.8) I get:

error: there is no corresponding function to call in IsIn (MyType &, <brace-closed initializer list>) '

I know I can do it, but this is a lot of cool:

if (IsIn(x, std::initializer_list<MyType>{1, 2, 3 })) ...

      

What's the elegant solution?

UPDATE: I haven't thought about compile time and run time, and I still can't decide if there is a clear winner. Mine for IsIn(x, {})

sure has more run loop overhead and copies initializer_list values, but also works with any container. The mechanism will ... == any_of(...

probably compile harder code and not copy, but only works with direct ones (this was my original example), not containers, and sitax (to me) seems a little less direct.

Since this is a kind of tie, I award his thanks.

Thanks everyone for the discussion!

+3


source to share


4 answers


I apologize for the shameless plugin, but I think it solves the OP's problem.

You can use this library :



#include "smart_conditions.hpp"
using namespace smart_conditions;

// ...

if (x == any_of (1, 2, 3))
{
    // ...
}

      

It supports other relational operators, it works at compile time ( constexpr

) if all operands are known at compile time and makes no copies . It also works with mixed types , which means it if (std::string("x") == any_of ("x", "y"))

compiles just fine.

+1


source


The solution was right under my nose ...



template<typename Val>
bool IsIn(Val val, std::initializer_list<Val> const &cont)
    {
    return boost::find(cont, val) != cont.end(); // include <boost/range/algorithm.hpp>
    // Or if you don't want boost, include <algorithm>
    // return std::find(cont.begin(), cont.end(), val) != cont.end();
    }

      

+3


source


Another little idea:

template<typename T, typename ... Args>
struct in_impl
{
    in_impl(T const& t, Args const& ... args) : val({t, args ...}) {}

    std::array<T, sizeof ...(Args) + 1> val;
};


template<typename T, typename ... Args>
bool operator==(T const& t, in_impl<T, Args ...> const& in)
{
    return std::find(std::begin(in.val), std::end(in.val), t) != std::end(in.val);
}


template<typename T, typename ... Args>
auto in(T const& t, Args const& ... args)
{
    return in_impl<T, Args ...>(t, args ...);
}

      

This can be used like

int main()
{
    if(1 == in(1,2,3) )
    {
        std::cout<<"1 is in"<<std::endl;
    }
}

      

DEMO

It T

could be a bit of work to get the lead type , but the idea should be clear.

+2


source


There are 2 cases in which you can call container.find(value)

and another where you call std::find(container.begin(), container.end(), value)

:

template<typename IteratorType, typename Type>
bool
contains ( IteratorType first, IteratorType last, Type const& value )
{
    return std::find ( first, last, value ) != last;
}


template <template <typename, typename ...> class ContainerType, typename KeyType, typename... Types>
bool
contains_key
    ( ContainerType <KeyType, Types ...> const& container
    , KeyType const& key
    )
{
    return container.find ( key ) != container.end ( );
}

      

0


source







All Articles