如何分支/切换多个条件? [英] How to branch/switch on multiple conditions?

查看:131
本文介绍了如何分支/切换多个条件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在多个条件分支,而不写代码看起来像一团糟? C ++ 11或C ++ 14中的语法糖值得赞赏。

  #include< iostream> 

枚举状态
{
STATE_1,
STATE_2,
STATE_3,
STATE_4,
STATE_5,
STATE_6 ,
STATE_7,
STATE_8,
};

state f(int a,bool b,const std :: string& str)
{
//如何:
if(a < )
{
if(b == false)
{
if(str!=morning)
{
return STATE_1;
}
else
{
return STATE_2;
}
}
else
{
if(str!=morning)
{
return STATE_3;
}
else
{
return STATE_4;
}
}
}
else // a> = 0
{
if(b == false)
{
if(str!=morning)
{
return STATE_5;
}
else
{
return STATE_6;
}
}
else
{
if(str!=morning)
{
return STATE_7;
}
else
{
return STATE_8;
}
}
}
}

int main()
{
std :: cout< State:< f(1,true,morning)<< std :: endl;
}


解决方案

p>

功能:




  1. 保留缺少案例的编译器检查,


  2. 案例的编译时评估意味着零运行时开销 p>


  3. 没有宏可以污染全局命名空间,并随机阻止纯标题库工作: - )




缺点:




  1. 需要预定义一些样板枚举

    > code> #include< iostream>
    #include< utility>
    #include< sstream>
    #include< string>

    namespace detail {

    template< size_t N> struct boolean_value;
    template< size_t N> using boolean_value_t = typename boolean_value< N> :: type;
    template< size_t N> constexpr auto to_int(boolean_value_t< N> b){return static_cast< int>(b) };
    template< size_t N> constexpr auto to_boolean_value(int i){return static_cast< boolean_value_t< N>(i); };

    模板<> struct boolean_value< 1> {
    枚举类型{bit0,bit1};
    };

    模板<> struct boolean_value< 2> {
    枚举类型{bit00,bit01,bit10,bit11};
    };

    模板<> struct boolean_value< 3> {
    枚举类型{bit000,bit001,bit010,bit011,bit100,bit101,bit110,bit111};
    };

    模板< class ... Args,size_t ... Is>
    static constexpr auto make_bitfield(std :: tuple< Args ...> t,std :: index_sequence< Is ...>)
    {
    #if __cplusplus> 201402L
    int accum =(0 | ... |(std :: get< Is>(t)?(1< Is):0)
    #else
    int accum = 0;
    using expand = int [];
    (void)expand {(std :: get< Is>(t)?accum | =(1<< Is):0)...}
    #endif
    return to_boolean_value< sizeof ...(Is)>(accum);
    }

    }

    template< class ... Args>
    constexpr
    auto mcase(Args& ... args)
    {
    return detail :: make_bitfield(std :: make_tuple(bool(std :: forward& (args))...),
    std :: index_sequence_for< Args ...>());
    }

    //小功能来击败优化器,否则ang整个程序!
    auto get_result()
    {
    using namespace std;

    istringstream ss(foo 2);
    auto result = tuple< string,int>();
    ss>> get< 0>(result)> get< 1>(结果);
    return result;
    }

    int main()
    {
    using namespace std;
    const auto result = get_result();
    const auto& s1 = std :: get< 0>(result);
    const auto& v1 = std :: get< 1>(result);

    switch(mcase(s1 ==foos,v1 == 2))
    {
    case mcase(true,true):
    cout< < mcase(true,true)<< endl;
    break;

    case mcase(false,false):
    cout<< mcase(false,false)<< endl;
    break;
    }
    return 0;
    }



    示例编译器输出:



      ./ mswitch.cpp:114:12:warning:在开关[-Wswitch]中不处理枚举值'bit01'和'bit10'
    switch(mcase ==foos,v1 == 2))
    ^
    1生成警告。
    ./mswitch.cpp:114:12:warning:在开关中不处理枚举值'bit01'和'bit10'[-Wswitch]
    switch(mcase(s1 ==foos,v1 == 2))
    ^
    1生成警告。



    运行时输出:



      3 


    Is there a way to branch on multiple condition without writing code that looks like a mess? Syntaxic sugar in C++11 or C++14 would be appreciated.

    #include <iostream>
    
    enum state
    {
        STATE_1,
        STATE_2,
        STATE_3,
        STATE_4,
        STATE_5,
        STATE_6,
        STATE_7,
        STATE_8,
    };
    
    state f(int a, bool b, const std::string& str)
    {
        // How not to:
        if (a < 0)
        {
            if (b == false)
            {
                if (str != "morning")
                {
                    return STATE_1;
                }
                else
                {
                    return STATE_2;
                }
            }
            else
            {
                if (str != "morning")
                {
                    return STATE_3;
                }
                else
                {
                    return STATE_4;
                }
            }
        }
        else // a >= 0
        {
            if (b == false)
            {
                if (str != "morning")
                {
                    return STATE_5;
                }
                else
                {
                    return STATE_6;
                }
            }
            else
            {
                if (str != "morning")
                {
                    return STATE_7;
                }
                else
                {
                    return STATE_8;
                }
            }
        }
    }
    
    int main()
    {
        std::cout << "State: " << f(1, true, "morning") << std::endl;
    }
    

    解决方案

    here's my version:

    Features:

    1. Preserves compiler checks for missing cases and gives informative messages about which cases were missed.

    2. Compile-time evaluation of cases means zero runtime overhead

    3. No macros to pollute the global namespace and randomly prevent header-only libraries from working :-)

    drawbacks:

    1. Requirement to predefine some boilerplate enums (once only, in the library which I have done for you)

    Code:

    #include <iostream>
    #include <utility>
    #include <sstream>
    #include <string>
    
    namespace detail{
    
        template<size_t N> struct boolean_value;
        template<size_t N> using boolean_value_t = typename boolean_value<N>::type;
        template<size_t N> constexpr auto to_int(boolean_value_t<N> b) { return static_cast<int>(b); };
        template<size_t N> constexpr auto to_boolean_value(int i) { return static_cast<boolean_value_t<N>>(i); };
    
        template<> struct boolean_value<1> {
            enum type { bit0, bit1 };
        };
    
        template<> struct boolean_value<2> {
            enum type { bit00, bit01, bit10, bit11 };
        };
    
        template<> struct boolean_value<3> {
            enum type { bit000, bit001, bit010, bit011, bit100, bit101, bit110, bit111 };
        };
    
        template<class...Args, size_t...Is>
        static constexpr auto make_bitfield(std::tuple<Args...> t, std::index_sequence<Is...>)
        {
    #if __cplusplus > 201402L
            int accum = (0 | ... | (std::get<Is>(t) ? (1 << Is) : 0));
    #else
            int accum = 0;
            using expand = int[];
            (void) expand { (std::get<Is>(t) ? accum |= (1 << Is) : 0) ... };
    #endif
            return to_boolean_value<sizeof...(Is)>(accum);
        }
    
    }
    
    template<class...Args>
    constexpr
    auto mcase(Args&&...args)
    {
        return detail::make_bitfield(std::make_tuple(bool(std::forward<Args>(args))...),
                                     std::index_sequence_for<Args...>());
    }
    
    // little function to defeat the optimiser, otherwise clang inlines the whole program!
    auto get_result()
    {
        using namespace std;
    
        istringstream ss("foo 2");
        auto result = tuple<string, int>();
        ss >> get<0>(result) >> get<1>(result);
        return result;
    }
    
    int main()
    {
        using namespace std;
        const auto result = get_result();
        const auto& s1 = std::get<0>(result);
        const auto& v1 = std::get<1>(result);
    
        switch(mcase(s1 == "foo"s, v1 == 2))
        {
            case mcase(true, true):
                cout << mcase(true, true) << endl;
                break;
    
            case mcase(false, false):
                cout << mcase(false, false) << endl;
                break;
        }
        return 0;
    }
    

    Example Compiler Output:

    ./mswitch.cpp:114:12: warning: enumeration values 'bit01' and 'bit10' not handled in switch [-Wswitch]
        switch(mcase(s1 == "foo"s, v1 == 2))
               ^
    1 warning generated.
    ./mswitch.cpp:114:12: warning: enumeration values 'bit01' and 'bit10' not handled in switch [-Wswitch]
        switch(mcase(s1 == "foo"s, v1 == 2))
               ^
    1 warning generated.
    

    Runtime Output:

    3
    

    这篇关于如何分支/切换多个条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆