2015-09-07 10 views
7

私はこれに対する答えをすでに知っていますが、それは価値があります。テンプレートの専門用語をタイプリストから宣言できますか?

template <typename ...Ts> 
struct typelist{}; 

いくつかのオブジェクトが含まれています:

struct foo{}; 
struct bar{}; 
struct quux{}; 

using objects = typelist<foo, bar, quux>; 

は、今私は、これらのオブジェクトのいずれかを取ることができますテンプレートクラス( baz)を持っている

だから、私はtypelistにを持っていると言います。しかし、コードベースのサイズとコンパイル時間のために、テンプレート化されたメソッドの実装をcppファイルに入れたいと思っています。

は、だから私は持っているbaz.cppの下部にある:

template <> class baz<foo>; 
template <> class baz<bar>; 
template <> class baz<quux>; 

問題は、私はbazのようなクラスがたくさんあるし、彼らはで動作するオブジェクトのリストも絶えず変化しています。だから...とにかく私は単一のタイプリストのオブジェクトを保持し、それを各bazのようなオブジェクトのcppファイルで使用することができますか?次に、新しいオブジェクトを作成したときにタイプリストを更新するだけです。すべてのオブジェクトファイルが再構築されます。

+0

* specialize *は明示的に*インスタンス化*する必要はありません。 – Jarod42

+0

これは間違いなくマクロを使って行うことができます。これが残りのコードベースから分離されていることを考えれば、それだけじゃないの? –

答えて

9

template <> class baz<foo>;行は特殊化を宣言していますが、テンプレートのインスタンス化は行いません。

これを直接行う方法はないと思いますが、メタプログラミングを行う必要があります。

#define TYPES (foo)(bar)(quux) 

using objects = typelist< BOOST_PP_SEQ_ENUM(TYPES) >; 

// Generate extern template declarations in the header 
#define EXTERN_TEMPLATE_BAZ(r, data, arg)\ 
    extern template class baz<arg>; 

BOOST_PP_SEQ_FOR_EACH(EXTERN_TEMPLATE_BAZ, _, TYPES) 

// Generate template instantiations in the .cpp 
#define TEMPLATE_BAZ(r, data, arg)\ 
    template class baz<arg>; 

BOOST_PP_SEQ_FOR_EACH(TEMPLATE_BAZ, _, TYPES) 

はプリプロセッサなしでこれを行う方法があるかもしれませんが、これを行うことはbazタイプの追加要件を課す:あなたは、すべての必要なコードを生成するためにBoost.Preprocessorを使用することができます。要点は、すべてのメソッドを含め、インスタンス化する必要があるコンテキストで型を使用することです。

+0

誰もがブーストを使用しているわけではありません。 –

+2

だから?それにもかかわらず、有効な解決策です。 –

+0

この解決策は機能しますが、質問者が望むものではないかもしれません。 Boostは標準C++の一部ではありません。 –

3

これは、プリプロセッサを使用しなければ不可能だと確信しています。引数からテンプレート引数パックを再構築できますが、引数のインスタンスを実際に渡す必要があります。これは、最適ではないようです。第2に、明示的なテンプレートのインスタンス化はブロックスコープ(テンプレート関数)では許可されないため、別のテンプレートを明示的にインスタンス化するテンプレートを書く方法はありません。

Nirが示しているように、なぜX Macroを使用しないのですか?

#define MY_FOREACH_TYPES(func, ...) \ 
    func(type1, ##_VA_ARGS__) \ 
    func(type2, ##_VA_ARGS__) \ 

#define MY_INSTANTIATE(Type, Class) \ 
    template <> class Class<Type>; 

MY_FOREACH_TYPES(MY_INSTANTIATE, bar) 

タイプリストが変更されたときに、MY_FOREACH_TYPESを更新してください。

+0

X-Macroについて言及してくれてありがとうございます。ウィキのリンクが最高です!人々はXマクロを使わないように何を知っていますか? (追跡/デバッグが難しいことを除いて) – javaLover

2

//Header file 

#define BAZ_OBJS \ 
    BAZ_BEGIN foo \ 
    BAZ_AND  bar \ 
    BAZ_AND  quux \ 
    BAZ_END 

#define BAZ_BEGIN 
#define BAZ_AND , 
#define BAZ_END 
using objects = typelist<BAZ_OBJS>; 
#undef BAZ_BEGIN 
#undef BAZ_AND 
#undef BAZ_END 

#define BAZ_BEGIN BAZ_EXTERN template class baz< 
#define BAZ_END >; 
#define BAZ_AND BAZ_END BAZ_BEGIN 

#ifdef MY_IMPLEMENTATION_CPP //cpp should define it before including the header file 
#define BAZ_EXTERN 
#else 
#define BAZ_EXTERN extern 
#endif 

BAZ_OBJS 
3

まず物事最初の普通のプリプロセッサと連動するバージョン:明示的なクラステンプレートのインスタンス化のための正しい構文は、明示的なクラステンプレートの特殊化(前方宣言である

template class baz<foo>; 
template class baz<bar>; 
template class baz<quux>; 

ないtemplate <> class baz<foo>です)。

一つの可能​​性はbaz<foo>baz<bar>baz<quux>の暗黙のインスタンス生成を強制するこの

template <template <typename> class T, typename... Args> 
class for_each_class : T<Args>... 
{ 
}; 

// Instantiate 
template class for_each_class<baz, foo, bar, quux>; 

のように見えるクラスをインスタンス化することであろう。しかし、これはtypelistから作成したいと考えています。 typelistはすでに特殊化されたテンプレートであり、typelisttypelistのテンプレートパラメータを使ってC++で反復処理する方法はありません。

マクロを使用することもできますが、マクロでも元のtypelistは使用できません。私はあなたの問題は、与えられたtypelistで解決策ではないと結論づけます。

解決策として、可能であれば、私はテンプレートインスタンス化をコンパイラに任せます。この場合、未使用のテンプレートはインスタンス化されません。遅いコンパイルは、meta-programs are specifiedの方法によるものです。

+0

これは 'baz '、 'baz '、 'baz 'をインスタンス化しません。 – Barry

+0

テンプレートであるメンバーはインスタンス化されないためです。 – Barry

+0

@Barry私の記事をもう一度読んでください。私はこれが 'baz 'などをインスタンス化するとは言っていませんが、なぜこれがマクロなしでできないのか説明しています。 –

1

これはトリックです。最終的には、1つの(または全く)タイプのタイプリストの初期化を行います。

template <typename Head, typename ...Tail> 
struct typelist{ 
    typedef baz<Head> head_t; 
    typedef typelist<Tail...> tail_t; 
}; 
+0

いいえ、 'baz'をインスタンス化しません。 –

+0

'baz 'が 'typelist 'の属性だったら?私は現在それをテストすることができません。私が入手した最新のコンパイラはgcc4.3です。 – prgasp77

+0

どのような属性ですか?テンプレートのインスタンス化を実行する属性は認識していません。 –

関連する問題