0

テンプレートの列挙型引数を使用して、2 番目の引数であるクラスを制限し、列挙型のメンバーをテンプレート化されたパラメーターとして引数として取得したいと考えています。コードでは、これは次のようになります。

CObject<EObjectTag, CSubObject<EObjectTag::CAT_A>> cObject;

ただし、これは機能するはずです。

CObject<EObjectTag, CSubObject<ENotAnObjectTag::CAT_OTHER>> cObject;

ENotAnObjectTag::CAT_OTHERは の要素ではないため、失敗するはずですEObjectTag

これの私の実装(試み)は次のとおりであり、コンパイル中に(gccバージョン4.9.2(Ubuntu 4.9.2-10ubuntu13)で)エラーメッセージが表示されます。

source.cc:16:45: エラー: 'SUBOBJECT_TAG' はこのスコープ構造体 CObject で宣言されていません>

#include <iostream>
#include <typeinfo>

enum class EObjectTag {CAT_A, CAT_B, CAT_OTHER};

// CSubObject
template<class OBJECT_TAG_T, OBJECT_TAG_T OBJECT_TAG>
struct CSubObject { OBJECT_TAG_T m_tTag = OBJECT_TAG; };

// CObject - Forward declaration
template <class SUBOBJECT_TAG_T, template <SUBOBJECT_TAG_T SUBOBJECT_TAG> class SUBOBJECT_T>
struct CObject;

// CObject - Specialization
template <class SUBOBJECT_TAG_T, template <SUBOBJECT_TAG_T SUBOBJECT_TAG> class SUBOBJECT_T>
struct CObject<SUBOBJECT_T<SUBOBJECT_TAG_T, SUBOBJECT_TAG>>
{
   public:
      SUBOBJECT_T<SUBOBJECT_TAG_T, SUBOBJECT_TAG> m_cSubObject;
};

int main() {
   // The aim is that the second object only accepts a tag that 
   // belongs to EObjectTag
   CObject<EObjectTag, CSubObject<EObjectTag::CAT_A>> cObject;

   return 0;
}

これの最後の使用例では、CSubObject を CObject に置き換えて、再帰を使用してタグ付きオブジェクトの階層を定義できるようにします。これには、可変個引数テンプレートを使用して同じレベルの複数のオブジェクトを含める必要もあります。例えば:

/* EBase, */
CObject</*EBase::BASE,*/ EObject,
    CObject<EObject::INIT, EInitObject,
        CObject<EInitObject::INIT_FOO>,
        CObject<EInitObject::INIT_BAR>,
    >,
    CObject<EObject::COUNT, ECountObject,
        CObject<ECountObject::COUNT_FOO>,
        CObject<ECountObject::COUNT_BAR>,
    >,
> cMyObjectHierarchy;

EBase (ライブラリ内部の列挙型) へのコメント アウトされた参照は、CObject のテンプレート パラメーターの一貫性を保つためにあります。(可能であれば) テンプレートの特殊化または既定の引数を介して自動的にこれを行う予定です。

このオブジェクトの階層を指定する私の目標には、さらに次のものが含まれます。

  1. このライブラリのユーザーに、プログラムで追加のクラスまたは構造体を定義することを強制しないでください
  2. 列挙型を使用して CObject をテンプレート化することにより、コンパイル時のチェックを活用します。列挙型の関数は、すべての CObject に共通の一連の関数の引数としてその列挙型を使用します。
4

2 に答える 2

2

の引数はtemplate <SUBOBJECT_TAG_T SUBOBJECT_TAG> class SUBOBJECT_Tテンプレートであり、テンプレートのインスタンスではありません。 はテンプレートではなく、テンプレートによって生成され たであるためCSubObject<blah>、 kind と一致することはできません。パラメータは型ではなくテンプレートです。template<...>classCSubObject<blah>template<...>class

また、CSubObject種類は であり、 ではありtemplate<class T, T> classませんtemplate<SUBOBJECT_TAG_T>class。これは 2 つの引数を取ります。最初は型、2 番目はその型の定数です: kindtemplate<SUBOBJECT_TAG_T>classは type の引数を 1 つ取るテンプレートですSUBOJECT_TAG_T。これらは無関係な種類のテンプレートです。

次に、テンプレートの特殊化に問題があるようです。テンプレートの専門化は、主要な専門化のパターン マッチングです。それらは「新しいオーバーロード」ではありません。したがって、への引数は、 expectsCObjectの主な特殊化である引数の種類と最初に一致する必要があります。CObject内部のものは、特殊化template< blah >の一部でパターンを一致させるために使用されます。CObject< blah >

一般に、テンプレート引数ではなく、マクロにのみすべて大文字を使用するのが慣例です。

これらはすべて、質問のコードの問題です。あなたのコードには明確な問題の記述や質問が欠けているので、私にできる最善のことは、あなたの無数の問題に対する修正を説明することです.


質問を少し修正しました。

template<class T, class U>
struct CObject;

template<class T, template<class Q, Q>class Z, T t>
struct CObject< T, Z<T, t> > {
};

実例

ここでもCSubObject<EObjectTag, EObjectTag::CAT_A>、2 番目のパラメーターとして渡す必要があります。

専門分野を追加することもできます:

template<class T, template<T>class Z, T t>
struct CObject< T, Z<t> > {
};

があれば、template<EObjectTag tag> struct Example;それも可能CObject< EObjectTag, Example<EObjectTag::bob> >です。

于 2015-10-23T15:22:09.527 に答える
1

コンパイルできるようにいくつかの変更を加えました。これが実際にあなたがやりたいことをするかどうかは100%わかりませんが。Yakk の答えのほとんどに同意します。

注:ある列挙型の型と別の列挙型の値を意図的に混合して、コンパイル時エラーが実際にトリガーされることを確認しようとしたため、以下はコンパイルされません。

#include <iostream>
#include <typeinfo>

enum class EObjectTag {CAT_A, CAT_B, CAT_OTHER};
enum class FObjectTag {DOG_A, DOG_B, DOG_OTHER};

// CSubObject
template<typename OBJECT_TAG_T, OBJECT_TAG_T OBJECT_TAG>
struct CSubObject { OBJECT_TAG_T m_tTag = OBJECT_TAG; };

// CObject - Specialization
template <class SUBOBJECT_TAG_T, SUBOBJECT_TAG_T SUBOBJECT_TAG, template <typename TYPE_T, TYPE_T TYPE> class SUBOBJECT_T>
struct CObject
{
   public:
      SUBOBJECT_T<SUBOBJECT_TAG_T, SUBOBJECT_TAG> m_cSubObject;
};

int main() {
   // The aim is that the second object only accepts a tag that 
   // belongs to EObjectTag
   CObject<EObjectTag, EObjectTag::CAT_A, CSubObject> cObject1;
   CObject<EObjectTag, FObjectTag::DOG_B, CSubObject> cObject2;

   return 0;
}
于 2015-10-23T15:31:21.040 に答える