2

ソースコンパイラのソースを書いていますが、瞬時に正しいテンプレートオブジェクトをインスタンス化できるようにするために、if文を継承しています。これらのオブジェクトはbool...を必要とするため、いくつかは正義を必要とすることがあり、他は多くを必要とすることがあります。それは次のようになります:Variadic動的値のテンプレートタイプ

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私はメタプログラムを使用したいと思います。しかし、私はいくつかの重大な困難に直面しています... 私の世代の間、私は必要なオブジェクトの数とどれくらいの "ブール"が必要かを知っています。

最初のステップは、ブール値のセットを取っテンプレート構造に「何かをする」の部分をカプセル化することでした:

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(); 
    } 
}; 

、それが完了していない:私は、私の考えは、現在、そのように作成された1 + 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と私に言って、それを他の人と交換する、それは同じことを言う...

誰かがアイデアを持っていますか? 最後に、私は(または同等)のような私の関数を呼び出すしたいと思います:bool_setを作成します

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

を各初期化子リストがbool_setであり、このgenerate_the_do_somethingは(?機能の)構造であり、それらと一緒にdo_something()と呼んでください。

答えて

1

あなたはそれが比較的簡単です(完成bool_setをパックする)std::tupleを使用して、次の例のように、特定のセパレータで

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

bool秒のセットを分離するために受け入れた場合。

#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{}); 
} 

は(パラメータなしcall()std::enable_if)SFINAEの使用を観察してか、end_set{}を終了せずにcall_do_something()の呼び出しを許可する例(コンパイル...少なくとも)以下の作業を参照してください。

+0

ありがとうございました!私は関数 "func"にパラメータを追加するためにそれを修正することに成功しました:) 私はついに 'std :: enable_if'を必要としませんでしたが、それはどのように動作するのか、 :) – Viridya

関連する問題