本文介绍了将布尔标记更改为模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 假设我有一个具有四个布尔标志的多功能函数: int do_something(int arg,bool flag1,bool flag2 ,bool flag3,bool flag4){ for(int i = 0; i if(flag1) //做某事1 if flag2) //做某事2 if(flag3) //做某事3 if(flag4) //做某事4 / / Do something else 5 } } 但我不想在内循环中的这些标志上分支的任何代价,所以我将它们改为模板(允许编译器优化掉条件语句): template< bool flag1,bool flag2,bool flag3,bool flag4> int do_something_helper(int arg){ for(int i = 0; i if(flag1) //做某事1 if(flag2) //做某事2 if(flag3) //做某事3 if(flag4) //做某事4 // Do something else 5 } } 现在写do_something方法?我知道的唯一方法如下: int do_something(int arg,bool flag1,bool flag2,bool flag3,bool flag4 ){ if(flag1){ if(flag2){ if(flag3){ if(flag4){ return do_something_helper< true,true,true ,true>(arg); } else { return do_something_helper< true,true,true,false>(arg); } } else { if(flag4){ return do_something_helper< true,true,false,true>(arg) } else { return do_something_helper< true,true,false,false>(arg); } } // ...你得到图片} 有没有办法让编译器自动编写上面的代码,所以我不必在我漂亮的代码库中包含这个丑陋的怪物?解决方案我会做一个函子和一组参数,参数索引和范围。然后我将替换索引的参数与 std :: integral_constant< type,value> 并调用函子。 bool 是最简单的,因为范围很明显,所以我先写一个。 可以链接这样的替换和函子,用编译时类型替换 bool 中的每一个。我将使用相同的函子为他们所有,与N重载,esch替换 bool 与 std :: integral_constant< bool,X> 其中 X 是模板参数。 最后一个将调用final方法,用 integral_constant 而不是 bool 。 请注意,这扩展为实例化的指数数量,所以要小心。 参数操作代码很有趣。 / p> 以下是即时示例 。 有趣的是,执行上述操作的样板可能仍然比较庞大,但希望减少打字错误和更容易测试。 #include< iostream> #include< tuple> 模板< unsigned ... Is> struct indexes {typedef indexes< Is ...>类型;}; template< unsigned min,unsigned max,unsigned ... Is> struct make_indexes:make_indexes< min,max-1,max-1,Is ...> {}; template< unsigned min,unsigned ... is> struct make_indexes< min,min,Is ...> ;: indexes< Is ...> {}; template< unsigned max,unsigned min = 0> using Indexes = typename make_indexes< min,max> :: type; template< unsigned index,typename Functor,typename ... Args,unsigned ... Before,unsigned ... After> void map_bool_to_compile_time_helper(indices< Before ...>索引< After ...>,Functor& f,std :: tuple< Args ...> args) { if(std :: get< index>(args)){ std :: forward< Functor>(f)(std :: get< Before>(args)...,std :: true_type (),std :: get< After>(args)...); } else { std :: forward< Functor>(f)(std :: get< Before>(args)...,std :: false_type(),std :: get< After> (args)...) } } template< unsigned index,typename Functor,typename ... Args> void map_bool_to_compile_time(Functor& f,Args& ... args) { map_bool_to_compile_time_helper< index>(Indexes< index>(),Indexes< sizeof ... Args),索引+ 1>(),std :: forward< Functor>(f),std :: make_tuple< Args& ); } template< typename Functor,unsigned ... indexes> struct map_bools_to_compile_time_helper; 模板< typename函子,无符号索引,无符号...索引> struct map_bools_to_compile_time_helper< Functor,index,indexes ...> { Functor&& F; map_bools_to_compile_time_helper(Functor&& in):f(std :: forward< Functor>(in)){} template< typename ... Args> void operator()(Args& ... args)const { map_bool_to_compile_time< index>(map_bools_to_compile_time_helper< Functor,indexes ...> {std :: forward< Functor> },std :: forward< Args>(args)...); } }; template< typename Functor> struct map_bools_to_compile_time_helper< Functor> { Functor&& F; map_bools_to_compile_time_helper(Functor&& in):f(std :: forward< Functor>(in)){} template< typename ... Args> void operator()(Args& ... args)const { std :: forward< Functor>(f)(std :: forward< Args>(args)...) } }; template< unsigned ... Is,typename Functor,typename ... Args> void map_bools_to_compile_time(indexes< Is ...>,Functor& f,Args& ... args){ map_bools_to_compile_time_helper< Functor,Is ...> {std :: forward< Functor>(f)}(std :: forward< Args>(args)...) } struct test { template< bool b> void operator()(int x,std :: integral_constant< bool,b>){std :: cout< x }; struct test2 { template< bool b0,bool b1,bool b2> void operator()(int x,std :: integral_constant< bool,b0>,std :: integral_constant< bool,b1>,std :: integral_constant& std :: cout<< x ; } }; int main(){ map_bools_to_compile_time(indexes< 1>(),test(),1,true); map_bool_to_compile_time< 1>(test(),2,false); map_bools_to_compile_time(indexes< 1,2,3>(),test2(),3,true,false,true); } 更新支持任意数量的索引的任意数量的参数。 p> Suppose I have a versatile function with about four boolean flags:int do_something(int arg, bool flag1, bool flag2, bool flag3, bool flag4) { for(int i = 0; i < 1000000; i++) { if(flag1) // Do something 1 if(flag2) // Do something 2 if(flag3) // Do something 3 if(flag4) // Do something 4 //Do something else 5 }}But I don't want to incur any costs for branching on these flags in the inner loop so I change them to templates (allowing the compiler to optimize away the conditionals):template<bool flag1, bool flag2, bool flag3, bool flag4>int do_something_helper(int arg) { for(int i = 0; i < 1000000; i++) { if(flag1) // Do something 1 if(flag2) // Do something 2 if(flag3) // Do something 3 if(flag4) // Do something 4 //Do something else 5 }}How can I write the do_something method now? The only way I know is as follows:int do_something(int arg, bool flag1, bool flag2, bool flag3, bool flag4) { if(flag1) { if(flag2) { if(flag3) { if(flag4) { return do_something_helper<true,true,true,true>(arg); }else{ return do_something_helper<true,true,true,false>(arg); } }else{ if(flag4) { return do_something_helper<true,true,false,true>(arg); }else{ return do_something_helper<true,true,false,false>(arg); } } //... You get the picture}Is there some way to get the compiler to write the above code automatically so I don't have to include this ugly monstrosity in my beautiful code-base? 解决方案 What I would do is take a functor and a pack of arguments and an argument index and a range. Then I would replace the indexed argument with std::integral_constant<type, value> and call the functor. The bool case is easiest, as the range is obvious, so I would write that one first.Then you can chain such replaces and functors to replace each one of the bools with compile time types. I would use the same functor for them all, with N overloads, esch replacing one bool with std::integral_constant<bool, X> where X is a template parameter.The last one would then call the final method, with integral_constant instead of bool.Note that this expands to an exponential amount of instantiations, so be careful.The argument manipulation code would be fun to write.Here is a live example.Amusingly, the boilerplate to do the above is probably still bulkier, but hopefully less typo-prone and easier to test.#include <iostream>#include <tuple>template<unsigned...Is> struct indexes {typedef indexes<Is...> type;};template<unsigned min, unsigned max, unsigned...Is> struct make_indexes: make_indexes<min, max-1, max-1, Is...> {};template<unsigned min, unsigned...Is> struct make_indexes<min, min, Is...>: indexes<Is...> {};template<unsigned max, unsigned min=0>using Indexes = typename make_indexes<min, max>::type;template<unsigned index, typename Functor, typename... Args, unsigned... Before, unsigned... After>void map_bool_to_compile_time_helper( indexes<Before...>, indexes<After...>, Functor&& f, std::tuple<Args...> args ){ if (std::get<index>( args )) { std::forward<Functor>(f)( std::get<Before>(args)..., std::true_type(), std::get<After>(args)... ); } else { std::forward<Functor>(f)( std::get<Before>(args)..., std::false_type(), std::get<After>(args)... ); }}template<unsigned index, typename Functor, typename... Args>void map_bool_to_compile_time( Functor&& f, Args&&... args ){ map_bool_to_compile_time_helper<index>( Indexes<index>(), Indexes<sizeof...(Args), index+1>(), std::forward<Functor>(f), std::make_tuple<Args&&...>(std::forward<Args>(args)...) );}template<typename Functor, unsigned... indexes>struct map_bools_to_compile_time_helper;template<typename Functor, unsigned index, unsigned... indexes>struct map_bools_to_compile_time_helper<Functor, index, indexes...> { Functor&& f; map_bools_to_compile_time_helper(Functor&& in):f(std::forward<Functor>(in)) {} template< typename... Args> void operator()( Args&&... args) const { map_bool_to_compile_time<index>( map_bools_to_compile_time_helper<Functor, indexes...>{std::forward<Functor>(f)}, std::forward<Args>(args)... ); }};template<typename Functor>struct map_bools_to_compile_time_helper<Functor> { Functor&& f; map_bools_to_compile_time_helper(Functor&& in):f(std::forward<Functor>(in)) {} template<typename... Args> void operator()( Args&&... args) const { std::forward<Functor>(f)(std::forward<Args>(args)...); }};template<unsigned... Is, typename Functor, typename... Args>void map_bools_to_compile_time( indexes<Is...>, Functor&& f, Args&&... args ) { map_bools_to_compile_time_helper<Functor, Is...>{ std::forward<Functor>(f) }( std::forward<Args>(args)... );}struct test { template<bool b> void operator()( int x, std::integral_constant< bool, b > ) { std::cout << x << ": " << b <<"!\n"; }};struct test2 { template<bool b0, bool b1, bool b2> void operator()( int x, std::integral_constant< bool, b0 >, std::integral_constant< bool, b1 >, std::integral_constant< bool, b2 > ) { std::cout << x << ": " << b0 << b1 << b2 << "\n"; }};int main() { map_bools_to_compile_time( indexes<1>(), test(), 1, true ); map_bool_to_compile_time<1>( test(), 2, false ); map_bools_to_compile_time( indexes<1,2,3>(), test2(), 3, true, false, true );}Updated with support for any number of arguments at any number of indexes. 这篇关于将布尔标记更改为模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-24 18:32
查看更多