如何分支/切换多个条件? [英] How to branch/switch on multiple conditions?
问题描述
有没有办法在多个条件分支,而不写代码看起来像一团糟? 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>
功能:
-
保留缺少案例的编译器检查,
-
案例的编译时评估意味着零运行时开销 p>
-
没有宏可以污染全局命名空间,并随机阻止纯标题库工作: - )
缺点:
- 需要预定义一些样板枚举
> 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:
Preserves compiler checks for missing cases and gives informative messages about which cases were missed.
Compile-time evaluation of cases means zero runtime overhead
No macros to pollute the global namespace and randomly prevent header-only libraries from working :-)
drawbacks:
- 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屋!