c++ - 通过模板-模板参数使用枚举标记对象

标签 c++ templates c++11 enums template-templates

我想使用模板的枚举参数来限制第二个参数,一个类,反过来将枚举的成员作为参数作为模板参数。在代码中,我希望它看起来像这样:

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: error: ‘SUBOBJECT_TAG’ was not declared in this scope struct 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 的模板参数一致,我计划(如果可能)通过模板特化或默认参数自动执行此操作。

我指定此对象层次结构的目标还包括:

  1. 避免强制这个库的用户定义额外的类 或他们程序中的结构
  2. 通过 使用枚举对 CObject 进行模板化,其函数又使用该枚举 枚举作为所有 CObjects 共有的一组函数的参数

最佳答案

template <SUBOBJECT_TAG_T SUBOBJECT_TAG> class SUBOBJECT_T 的参数是模板,而不是模板的实例。 CSubObject<blah>无法匹配种类template<...>class ,因为 CSubObject<blah>是由模板而不是模板生成的类型template<...>class参数是模板,而不是类型。

此外,CSubObject很亲切template<class T, T> class , 不是 template<SUBOBJECT_TAG_T>class .它有两个参数,第一个是类型,第二个是该类型的常量:种类 template<SUBOBJECT_TAG_T>class是一个模板,它接受一个类型为 SUBOJECT_TAG_T 的参数.这些是不相关的模板。

其次,您似乎对模板特化有疑问。模板特化是您的主要特化的模式匹配。它们不是“新的重载”。所以参数 CObject必须首先匹配 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> > {
};

live example .

现在,你还需要通过 CSubObject<EObjectTag, EObjectTag::CAT_A>作为第二个参数。

您还可以添加专业:

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

如果你有一个 template<EObjectTag tag> struct Example; , 你可以 CObject< EObjectTag, Example<EObjectTag::bob> >

关于c++ - 通过模板-模板参数使用枚举标记对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33305628/

相关文章:

c++ - 有没有在模板中使用数值的有效方法?

c++ - 为什么我不能使用 tbb::task_scheduler_init 创建超过 32 个线程?

templates - 模板函数中的"No matching function call"

c++ - Qt 两个类互相访问

c++ - 使用 C++14 编译器而不是 C++11 进行编译时,性能会得到提升吗?

c++ - 在 C++ 中如何声明 std::array 的别名?

C++ 函数和类模板声明

c++ - 这个语法 "decltype(*(T*)(0)**(U*)(0)) "是什么意思?

c++ - 调试已发布软件的 C++ 核心文件

c++ - std::vector reserve() 和 push_back() 比 resize() 和数组索引快,为什么?