c++ - 来自动态值的 Variadic 模板类型

标签 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*/
    }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*/
    }
}

但有更多的条件和对象。我不能使用多态和指针,因为性能是我的应用程序和对象的关键点 AB被大量使用。

如果 if 而不是复杂的继承我想使用元编程。但是,我面临一些严重的困难...... 在我这一代,我知道我需要多少个对象以及它需要多少“bool”。

第一步是将“做某事”部分封装在采用 bool 值集的模板结构中:

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 with -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 集,如下例所示

call_do_something(false, true, end_set{}, false, false, true, end_set{});

使用 std::tuple(打包完成的 bool_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 over call() without parameters)允许调用 call_do_something()或没有结束 end_set{}

关于c++ - 来自动态值的 Variadic 模板类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46773112/

相关文章:

c++ - C 和 C++ 标准对假设的三元硬件架构的适应性如何?

c++ - 覆盖虚函数和隐藏非虚函数有什么区别?

c++ - 在 C++ 中添加互斥锁后结构中的赋值运算符

c++ - 头文件重定义错误 - cpp

c++ - 无法删除结构指针内的指针数组 (c++)

c++ - 是否可以仅从普通 C 或普通 C++ 控制屏幕上的像素而无需任何 opengl/directx 麻烦?

c++ - 在 map 中插入 std::string 和指向对象的共享指针

android-ndk: stoi/stof/stod/to_string 不是 'std' 的成员

c++ - 实例化一个 "function type"变量

C++ 模板 t 不是有效的模板类型