テンプレートの列挙型引数を使用して、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 のテンプレート パラメーターの一貫性を保つためにあります。(可能であれば) テンプレートの特殊化または既定の引数を介して自動的にこれを行う予定です。
このオブジェクトの階層を指定する私の目標には、さらに次のものが含まれます。
- このライブラリのユーザーに、プログラムで追加のクラスまたは構造体を定義することを強制しないでください
- 列挙型を使用して CObject をテンプレート化することにより、コンパイル時のチェックを活用します。列挙型の関数は、すべての CObject に共通の一連の関数の引数としてその列挙型を使用します。