来自动态值的可变参数模板类型
我正在为源编译器编写某种源代码,并且此刻我产生了一组if
语句,这些语句允许我实例化正确的模板对象。这些对象需要bool...
,所以有些可能需要合理的一个,其他许多。它看起来像:来自动态值的可变参数模板类型
if(unknow_at_compilation==1){
if(unknown2 == 3){
My_obj<true> A;
My_obj<true, false> B;
/*do something X*/
}else{
My_obj<true> A;
My_obj<false, false> B;
/*do same thing X*/
}else{
if(unknown2 == 3){
My_obj<false> A;
My_obj<true, true> B;
/*do same thing X*/
}else{
My_obj<false> A;
My_obj<false, true> B;
/*do same thing X*/
}
}
但有更多的条件和对象。我不能使用多态性和指针,因为性能是我应用程序中的关键点,并且对象A
和B
被大量使用。
而不是如果if
if
我想使用metaprogrammation该复杂的继承。然而,我面临一些严重的困难...... 在我这一代,我知道我需要的对象的数量以及需要多少“布尔”。
第一步是封装在模板结构中的“有所作为”部分以套布尔:
template<bool... val>
struct bool_set{};
template<typename T1, typename T2>
struct struct_do_something;
template<bool... b1, bool... b2>
struct struct_do_something<bool_set<b1...>, bool_set<b2...>>
{
static void do_something(){
My_obj<b1...> i;
My_obj<b2...> j;
/*Do something*/
}
};
这件作品,我可以把它像(例如):struct_do_something<bool_set<true, true>, bool_set<false, false>>::do_something();
然后,我写了一个使用条件生成单个bool_set
的结构。
template<bool... static_vals> //bool values of the currently created bool_set
struct bool_set_generator{
template<typename... Bool>
static void select(bool v1, Bool... dynamic_vals) //Conditions in parameters
{
if(v1)
return bool_set_generator<static_vals..., true>::select(dynamic_vals...);
else
return bool_set_generator<static_vals..., false>::select(dynamic_vals...);
}
static void select(){
/*I have a bool_set here -> I can "do something"*/
struct_do_something<bool_set<static_vals...>>::do_something();
}
};
很显然,这不是结束:我可以生成一个bool_set
所以我的想法是存储bool_set
已创建+目前这样创建的:
template <typename... Created, bool... static_val>
但是编译器(G ++ 5.4与-std = C++ 11)告诉我parameter pack ‘Created’ must be at the end of the template parameter list
和我与其他开关,它说相同...
有人有一个想法? 最后,我想打电话给我的功能一样,(或同等学历):(?函数)
generate_the_do_something<>::call({cond1, cond2}, {cond3, cond4, cond5});
每个初始化列表是bool_set
,这generate_the_do_something
是一种结构,将创建bool_set
和与他们联系do_something()
。
如果你接受了一套bool
s的特定分离器分离出来,如在使用std::tuple
(收拾完毕bool_set
)下面的例子
call_do_something(false, true, end_set{}, false, false, true, end_set{});
这是比较容易的。
请参见下面的工作(至少...编译)例如
#include <tuple>
template<bool...>
struct bool_set{};
struct end_set{};
template <bool...>
struct My_obj{};
template <typename, typename>
struct do_something;
template <bool... bs1, bool... bs2>
struct do_something<bool_set<bs1...>, bool_set<bs2...>>
{
static void func()
{
My_obj<bs1...> mo1;
My_obj<bs2...> mo2;
(void)mo1; // just to avoid a lot warnings
(void)mo2; // just to avoid a lot warnings
// do something else
}
};
template <typename, typename>
struct gtds; // ex generate_the_do_something
template <typename ... Ts, bool ... Bs>
struct gtds<std::tuple<Ts...>, bool_set<Bs...>>
{
template <typename ... As>
static void call (bool const & val, As const & ... as)
{
if (val)
gtds<std::tuple<Ts...>, bool_set<Bs..., true>>::call(as...);
else
gtds<std::tuple<Ts...>, bool_set<Bs..., false>>::call(as...);
}
template <typename ... As>
static void call (end_set const &, As const & ... as)
{ gtds<std::tuple<Ts..., bool_set<Bs...>>, bool_set<>>::call(as...); }
template <bool bsEmpty = (sizeof...(Bs) == 0U)>
static typename std::enable_if< ! bsEmpty >::type call()
{ do_something<Ts..., bool_set<Bs...>>::func(); }
template <bool bsEmpty = (sizeof...(Bs) == 0U)>
static typename std::enable_if<bsEmpty>::type call()
{ do_something<Ts...>::func(); }
};
template <typename ... Ts>
void call_do_something (Ts const & ... ts)
{ gtds<std::tuple<>, bool_set<>>::call(ts...); }
int main()
{
call_do_something(false, true, end_set{}, false, false, true);
call_do_something(false, true, end_set{}, false, false, true, end_set{});
}
观察使用SFINAE的(std::enable_if
超过call()
不带参数),以允许call_do_something()
通话有或没有结束end_set{}
。
非常感谢!我已经成功修改它以将参数添加到函数“func”:) 我终于不需要'std :: enable_if',但它是了解它如何工作以及何时使用它的好例子,再次感谢:) – Viridya