我想使用模板的枚举参数来限制第二个参数,一个类,反过来将枚举的成员作为参数作为模板参数。在代码中,我希望这看起来像:
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;
}
最后一个用例涉及用 CObject 替换 CSubObject,以便我们可以使用递归来定义标记对象的层次结构,这也需要使用可变参数模板来在同一级别拥有多个对象。例如:
/* 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 共有的一组函数的参数