Better way to say x == Foo::A || x == Foo::B || x == Foo::C || …?

前端 未结 8 599
醉酒成梦
醉酒成梦 2021-02-07 03:23

Let\'s say I have a bunch of well-known values, like this (but const char * is just an example, it could be more complicated):

const char *A = \"A\"         


        
相关标签:
8条回答
  • 2021-02-07 04:02

    (Edit: Turns out my original trick with a dummy type didn't work, I was misled by a lucky accident in my tests. Let's try that again...)

    With a couple of helper templates you can write a general solution for this kind of situation:

    template <typename T1> class Matcher {
    public:
        explicit Matcher(T1 t1): val(t1), flag(false) {}
        template <typename T2> Matcher& operator()(T2 t2)
            { flag |= val == t2; return *this; }
        operator bool() const { return flag; }
    private:
        T1 val;
        bool flag;
    };
    template <typename T1> Matcher<T1> match(T1 t1) { return Matcher<T1>(t1); }
    
    // example...
    string s = whatever;
    if (match(s)("foo")("bar")("zap")) { do_something(); }
    

    You can match against as many arguments as you want.

    0 讨论(0)
  • 2021-02-07 04:09

    This can be done using variadic functions in c++03 as follows:

    template <typename T>
    bool MatchesOne( T _lhs, int _count, ...)
    {
        va_list vl;
        va_start(vl,_count);
        for (int i=0;i<_count;i++)
        {
            int rhs=va_arg(vl,int);
            cout << "rhs = " << rhs << endl;
            if (_lhs == rhs) return true;
        }
        va_end(vl);
        return false;
    }
    
    int main(){
        float ff = 3.0;
        if (MatchesOne(ff, 5, 1, 2, 4, 5, 3))
        {
            cout << "Matches" << endl;
        }
        return 0;
    }
    

    If you know the types of all the expressions will have the same type as _lhs, you can change int rhs=va_arg(vl,int); to T rhs=va_arg(vl,T);

    You can also do this elegantly using variadic templates in c++11:

    template<typename T, typename T2>
    bool one_equal(const T & _v1, const T2 & _v2)
    {
        return _v1 == _v2;
    }
    
    template<typename T, typename T2, typename... Args>
    bool one_equal(const T & _v1, const T2 & _v2, Args... args)
    {
        return _v1 == _v2 || one_equal(_v1, args...);
    }
    
    ...
    
    if (one_equal(some_complicated_expression, v1, v2, v3, v4))
    {
    
    }
    

    Okay one final hack-ish solution. It works, but makes the implementer of this function do a lot of repetitive work.

    template <typename T1, typename T2>
    bool match_one(T1 _v1, T2 _v2)
    {
        return _v1 == _v2;
    }
    
    template <typename T1, typename T2, typename T3>
    bool match_one(T1 _v1, T2 _v2, T3 _v3)
    {
        return _v1 == _v3 || match_one(_v1, _v2);
    }
    
    template <typename T1, typename T2, typename T3, typename T4>
    bool match_one(T1 _v1, T2 _v2, T3 _v3, T4 _v4)
    {
        return _v1 == _v4 || match_one(_v1, _v2, _v3);
    }
    
    template <typename T1, typename T2, typename T3, typename T4, typename T5>
    bool match_one(T1 _v1, T2 _v2, T3 _v3, T4 _v4, T5 _v5)
    {
        return _v1 == _v5 || match_one(_v1, _v2, _v3, _v4);
    }
    
    0 讨论(0)
提交回复
热议问题