C++ 来自动态值的可变模板类型

C++ 来自动态值的可变模板类型,c++,c++11,templates,variadic-templates,template-meta-programming,C++,C++11,Templates,Variadic Templates,Template Meta Programming,我正在编写某种源代码到源代码的编译器,并且在某个时刻,我生成了一系列if语句,允许我实例化正确的模板对象。这些对象需要一个bool…,因此一些可能只需要一个,其他可能需要多个。它看起来像: if(unknow_at_compilation==1){ if(unknown2 == 3){ My_obj<true> A; My_obj<true, false> B; /*do something X*/ }els

我正在编写某种源代码到源代码的编译器,并且在某个时刻,我生成了一系列
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*/
    }
}
这部分工作正常,我可以这样称呼它(例如):
struct_do_something::do_something()

然后,我编写了一个结构,使用条件生成一个
bool\u集

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();
    }
};
但是编译器(g++5.4,带-std=c++11)告诉我,
参数包“Created”必须在模板参数列表的末尾,我将其与另一个进行切换,它说的是相同的

有人有主意吗? 最后,我想这样调用我的函数(或等效函数):

generate_the_do_something::call({cond1,cond2},{cond3,cond4,cond5});

每个初始值设定项列表都是一个
bool\u集
,这个
generate\u do\u something
是一个结构(函数的?),它将创建
bool\u集
,并用它们调用
do\u something()

如果您接受用特定的分隔符分隔
bool
集,如以下示例所示

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{});
 }
使用
std::tuple
(打包完成的
bool\u集
)相对容易

请参阅以下工作(至少…编译)示例

#包括
模板
结构布尔_集{};
结构结束集合{};
模板
结构My_obj{};
模板
结构做某事;
模板
结构做什么
{
静态void func()
{
我的目标是1;
My_obj mo2;
(void)mo1;//只是为了避免大量警告
(void)mo2;//只是为了避免很多警告
//做点别的
}
};
模板
结构gtds;//比如说做点什么
模板
结构gtds
{
模板
静态无效调用(布尔常量和值,作为常量和…作为)
{
if(val)
gtds::调用(as…);
其他的
gtds::调用(as…);
}
模板
静态void调用(end_set const&,As const&…As)
{gtds::call(as…;}
模板
静态typename std::enable_if<!bsEmpty>::类型调用()
{do_something::func();}
模板
静态typename std::enable_if::type call()
{do_something::func();}
};
模板
无效调用做某事(Ts const&…Ts)
{gtds::call(ts…);}
int main()
{
称你做某事(假,真,结束集{},假,假,真);
调用(false,true,end)set{},false,false,true,end(set{});;
}

注意使用SFINAE(
std::enable_if
over
call()
无参数)来允许调用
call_do_something()!我成功地修改了它,将参数添加到函数“func”:)我终于不需要
std::enable_if
,但这是一个很好的例子,可以了解它是如何工作的以及何时使用它,再次感谢:)
generate_the_do_something<>::call({cond1, cond2}, {cond3, cond4, cond5});
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{});
 }