以前のテンプレート パラメーターのサブタイプと等しい型の非型値であるテンプレート テンプレート パラメーターを渡そうとしています (これは読むのと同じくらい難しいことです!)、結果を単一のパラメーター化されたテンプレートに結合しようとした後、いくつかのビルド エラーが発生しました。
次のコードがあります (g++ 4.4.1 および -std=c++0x で問題なくコンパイルされます)。
#include <iostream>
using namespace std;
enum class Labels { A , B };
template <Labels L>
struct LabelTypeMap {
typedef int type_t;
};
template<> struct LabelTypeMap<Labels::B> { typedef double type_t; };
template <bool Enable=true>
struct Hold
{
typedef Labels enum_t;
};
template <>
struct Hold<true>
{
typedef Labels enum_t;
};
template< typename Holder , template< typename Holder::enum_t > class typeMap , bool Enable >
struct Whatever
{
template < typename Holder::enum_t label >
void Operate(typename typeMap<label>::type_t parameter) {};
};
template< typename Holder , template< typename Holder::enum_t > class typeMap >
struct Whatever< Holder , typeMap , true > : public Holder
{
template < typename Holder::enum_t label >
void Operate(typename typeMap<label>::type_t parameter) { cout << "operate on " << parameter << endl; };
};
template < bool Enable >
struct Now {
typedef Hold<true> MyHold; // <----- check this out!
typedef Whatever< MyHold , LabelTypeMap , Enable > concrete_t;
};
int main() {
Now< true >::concrete_t obj;
obj.Operate< Labels::A >( 3.222222222222222222222 );
obj.Operate< Labels::B >( 3.2222222222222222222 );
};
ただし、Now
テンプレートを見てください。ブール値によってパラメーター化された 2 つのメンバーがあります。ただし、囲んでいるテンプレートconcrete_t
の bool パラメータに依存しますが、依存しません。それを変更したいので、宣言を次のように置き換えます。Now
MyHold
Now
template < bool Enable >
struct Now {
typedef Hold<Enable> MyHold; // <----- boom!
typedef Whatever< MyHold , LabelTypeMap , Enable > concrete_t;
};
しかし、これにより次のエラーが発生します。
error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::enum_t <anonymous> > class typeMap, bool Enable> struct Whatever’
error: expected a template of type ‘template<typename Holder::enum_t <anonymous> > class typeMap’, got ‘template<Labels L> struct LabelTypeMap’
私はこれを十分に見つめてきましたが、この単純な変更がエラーを引き起こす理由を完全に理解できていないと言わざるを得ません。何か案は?
編集:これは(うまくいけば)熟考しやすくするための問題の最小限の説明です:
$ cat templatetemplate.cc
template <int i>
struct LabelTypeMap { typedef int type_t; };
template <bool>
struct Hold { typedef int type; };
template<typename Holder, template<typename Holder::type> class typeMap>
struct Whatever { };
template <bool Enable>
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap> concrete_t; };
Now<true>::concrete_t obj;
$ g++ -DENABLE=Enable -c templatetemplate.cc
templatetemplate.cc:11: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::type <anonymous> > class typeMap> struct Whatever’
templatetemplate.cc:11: error: expected a template of type ↵
‘template<typename Holder::type <anonymous> > class typeMap’, got ↵
‘template<int i> struct LabelTypeMap’
marcelo@macbookpro-1:~/play$
$ g++ -DENABLE=true -c templatetemplate.cc
(no error)