我有一个模板课
templateclass S { //... implementations };
和类型的一些股票类型实现U
,V
和W
:
typedef boost::mpl::vectoru_types; typedef boost::mpl::vector u_types; typedef boost::mpl::vector w_types;
我想用模板参数的所有可能组合测试类S,
typedef boost::mpl::vector< S, S , // ... S , > s_types;
像这样:
boost::mpl::for_each(test_func).
唯一的问题是有2**5**5 = 50种组合,我不希望逐个输入.
有没有办法s_types
用Boost :: mpl或Boost.Preprocessor 生成所有组合()?
谢谢.
添加了我最初的失败尝试:
我试图诉诸索引(因此定义u_types等)和部分模板专业化这样
namespace wrapper { templatestruct S_Wrapper { typedef S type; S_Wrapper() // auto test in the ctor { cout << "test result = " << test(type()); } // test with S static bool test(type t) { // implementations } // get stuck here, S_Wrapper s; // temp varible to invoke recursive-ness // what else to complete all recursive path? }; // specializations template <0, 0, 0> struct S_Wrapper { typedef S<0, 0, 0> type; // test with S // static bool test(type t) { // implementations } }; // get stuck here, too // what other specializations are ? // other specializations }
然后用
wrapper::S_Wrapper< mpl::size::type::value, mpl::size ::type::value, mpl::size ::type::value > s;
所有S类型都应进行调整和测试;
但是我没有通过确定覆盖所有组合
1)适当的特化和
2)struct S_Wrapper中的递归触发器
我的所有试验要么在运行时部分覆盖组合,要么在编译时扣除失败.
有什么想法吗?
受到Matthieu的启发,我想出了一个模板化的课程,Combine
这样我就可以在这两行中实现我的目标:
typedef Combine< u_types, v_types, w_type, print_typeid >::Generate<> base_generator_type; base_generator_type::Run();
这将打印所有生成的类型.
// example test implementation struct print_typeid { template< class U, class V, class W > static void run() { // print the typeinfo std::cout << total_recursions << ":" << typeid(U).name() << "," << typeid(V).name() << "," << typeid(W).name() << std::endl; } }; // solution implemented in one wrapper class namespace argument_combination { using boost::is_same; using boost::mpl::begin; using boost::mpl::end; using boost::mpl::next; using boost::mpl::if_; using boost::mpl::deref; unsigned int total_recursions = 0; struct end_of_recursion_tag { static void Run() { std::cout << "end of " << total_recursions << " recursions\n" ; } }; template < class UTypes, // Forward Sequence, e.g. boost::mpl::vector class VTypes, // Forward Sequence, e.g. boost::mpl::vector class WTypes, // Forward Sequence, e.g. boost::mpl::vector class TestFunc // class type that has a nested templated run() member function > struct Combine { // forward declaration template < class UIterator, class VIterator, class WIterator > class Generate; // this class implements recursion body template < class UIterator, class VIterator, class WIterator > struct Next { // u_begin is not necessary ;) // it would be cheaper not to pre-declare all of them since we force evaluation // however this dramatically increase the readability typedef typename begin::type v_begin; typedef typename begin ::type w_begin; typedef typename end ::type u_end; typedef typename end ::type v_end; typedef typename end ::type w_end; typedef typename next ::type u_next; typedef typename next ::type v_next; typedef typename next ::type w_next; typedef typename if_< is_same , typename if_< is_same , typename if_< is_same , end_of_recursion_tag, Generate< u_next, v_begin, w_begin > >::type, Generate< UIterator, v_next, w_begin > >::type, Generate< UIterator, VIterator, w_next > >::type type; }; // this class run test on generated types in thos round and go to next*/ template < class UIterator = typename begin ::type, class VIterator = typename begin ::type, class WIterator = typename begin ::type > struct Generate { // generate < > target type typedef typename Next< UIterator, VIterator, WIterator >::type next_type; static void Run() { // increment recursion counter ++total_recursions; // test on the generated types of this round of recursion TestFunc::run< typename deref ::type, typename deref ::type, typename deref ::type >(); // go to the next round of recursion next_type::Run(); } }; }; }// namespace argument_combination
Matthieu M... 9
如果您真正想要做的是生成所有可能解决方案的向量然后测试它们,您将必须使用预处理器为您生成所有这些解决方案.
但是,另一个解决方案是使用生成器:一个包装类,它将实例化所有解决方案并测试它们.您可能想咨询Loki的层次结构生成器(详细信息在本书中).
// never remember where they put boost::same_type :x #include#include #include #include #include using namespace boost::mpl; struct None { static void test() {} }; template class Generator; template struct Next { // u_begin is not necessary ;) // it would be cheaper not to pre-declare all of them since we force evaluation // however this dramatically increase the readability typedef typename begin ::type v_begin; typedef typename begin ::type w_begin; typedef typename next ::type u_next; typedef typename next ::type v_next; typedef typename next ::type w_next; typedef typename end ::type u_end; typedef typename end ::type v_end; typedef typename end ::type w_end; typedef if_< boost::same_type , if_< boost::same_type , if_< boost::same_type , None, Generator< u_next, UTypes, v_begin, VTypes, w_begin, WTypes > >, Generator< UIterator, UTypes, v_next, VTypes, w_begin, WTypes > >, Generator< UIterator, UTypes, VIterator, VTypes, w_next, WTypes> >::type type; }; template struct Generator { typedef S< deref ::type, deref ::type, deref ::type > S_type; typedef Next ::type next_type; static void test() { // test my variation of S S_Type my_S; test_func(my_S); // test the variations of my next and its next and... you get the idea :) next_type::test(); } }; // And finally int main(int argc, char* argv[]) { typedef Generator< begin ::type, u_types, begin ::type, v_types, begin ::type, w_types > base_generator_type; base_generator_type::test(); }
免责声明:此代码尚未编译,可能缺少一些include/typename/use指令......但我希望你明白我的观点.
如果您对设计模式有什么了解,它就会在每个步骤层添加另一轮测试的方式与"装饰器"或"复合"设计高度相似.
我还要注意,这需要更多的50行代码...但至少它会与矢量很好地成长:)
如果您真正想要做的是生成所有可能解决方案的向量然后测试它们,您将必须使用预处理器为您生成所有这些解决方案.
但是,另一个解决方案是使用生成器:一个包装类,它将实例化所有解决方案并测试它们.您可能想咨询Loki的层次结构生成器(详细信息在本书中).
// never remember where they put boost::same_type :x #include#include #include #include #include using namespace boost::mpl; struct None { static void test() {} }; template class Generator; template struct Next { // u_begin is not necessary ;) // it would be cheaper not to pre-declare all of them since we force evaluation // however this dramatically increase the readability typedef typename begin ::type v_begin; typedef typename begin ::type w_begin; typedef typename next ::type u_next; typedef typename next ::type v_next; typedef typename next ::type w_next; typedef typename end ::type u_end; typedef typename end ::type v_end; typedef typename end ::type w_end; typedef if_< boost::same_type , if_< boost::same_type , if_< boost::same_type , None, Generator< u_next, UTypes, v_begin, VTypes, w_begin, WTypes > >, Generator< UIterator, UTypes, v_next, VTypes, w_begin, WTypes > >, Generator< UIterator, UTypes, VIterator, VTypes, w_next, WTypes> >::type type; }; template struct Generator { typedef S< deref ::type, deref ::type, deref ::type > S_type; typedef Next ::type next_type; static void test() { // test my variation of S S_Type my_S; test_func(my_S); // test the variations of my next and its next and... you get the idea :) next_type::test(); } }; // And finally int main(int argc, char* argv[]) { typedef Generator< begin ::type, u_types, begin ::type, v_types, begin ::type, w_types > base_generator_type; base_generator_type::test(); }
免责声明:此代码尚未编译,可能缺少一些include/typename/use指令......但我希望你明白我的观点.
如果您对设计模式有什么了解,它就会在每个步骤层添加另一轮测试的方式与"装饰器"或"复合"设计高度相似.
我还要注意,这需要更多的50行代码...但至少它会与矢量很好地成长:)