从另一个模板类填充一个类的模板

时间:2011-09-28 15:22:40

标签: c++ templates

如果我有两个班级:

template <typename T>
struct Node
{
  ...
};

tempalte <typename T_Node, typename T>
struct NodeIterator
{
  T m_value;
};

NodeIterator<Node<int>, int>

我可以从T推断模板参数T_Node,而不会让Node类显式创建类似这样的typedef:

// To make it clear, yes I know this works, but I had to typedef the type
template <typename T>
struct Node
{
  typedef T node_type;
  ...
};

template <typename T_Node>
struct NoteIterator
{
  typedef typename T_Node::node_type node_type;

  node_type m_value;
};

NodeIterator<Node<int> >

如果没有,是否有一个原因我不能这样做(编译器已经知道T_Node和它所采用的类型T)除了“该功能不存在用C ++“?我问这个问题,因为通常有一个很简单的事情(至少在表面上),就像语言中缺少的一样。

6 个答案:

答案 0 :(得分:2)

为什么不将NodeIterator更改为类似的内容:

template <typename T>
struct NodeIterator
{
  typedef Node<T> node_type;

  node_type m_value;
};

这应该允许您创建NodeIterator<int>类型的对象。我认为这将是一个优雅的解决方案。 `

答案 1 :(得分:2)

没有typedef,那是不可能的。关键是编译器不知道T_Node本身就是模板的实例化。 Node<T>只是类型,仅此而已。

C ++知道三层实体:值,类型和模板。 Node是一个模板,Node<T>是一种类型。当您的类模板接受类型参数时,您无法再检查该类型的性质。

通过部分特化进行模式匹配是提取此类信息的唯一方法,并且您无需进行一些功能元编程。任何类型的检查通常被称为“类型特征”。这一切都归结为同样的事情,非常类似于你已经提出的建议,但也许这是另一种更通用的方式:

template <typename> struct ClassWithOneArg;

template <template <typename> class C, typename T>
struct ClassWithOneArg<C<T>>
{
  typedef T value_type;
};

现在你可以说:typedef typename ClassWithOneArg<T_Node>::value_type type;

答案 2 :(得分:1)

是。你尝试过的几乎是正确的,除了你忘了typename

typedef typename T_Node::node_type node_type;
       //^^^^^^^ note this!

您需要编写关键字typename,因为嵌套类型node_type是依赖类型

答案 3 :(得分:0)

不,你不能。你需要typedef。 C ++没有任何编译时反射支持,此功能适合。

它不在语言中的原因很简单:没有人在标准化过程中提出这样一个功能的好建议。这可能是因为这样的功能并非无足轻重。为什么你可能只是对获取模板参数感到满意,还有很多其他的地方需要考虑才能使整个功能看起来“圆”。

当你感兴趣时,你可以制定出这样的建议;)

答案 4 :(得分:0)

我认为你不能,但我认为你不应该这样做。使用typedef是一种成熟的做法;查看标准容器及其value_type等typedef。

您在另一个答案的评论中提到您不希望NodeIterator了解Node。它没有具体了解Node;它只需要其模板参数为某些类型,其中包含node_type类型。这可能是Node,也可能是其他内容,NodeIterator无需了解或关注。

答案 5 :(得分:0)

答案是否定的,你不能用C ++做到这一点。这就是为什么STL迭代器类型包含您试图避免的那些嵌套的typedef。此外,如果您想允许指向节点的指针(符合RandomAccessIterators的所有要求),依赖于这些嵌套类型会让您遇到麻烦。如果要将节点的原始指针包含为节点迭代器类型,则需要使用traits类,因为它们不能具有嵌套类型。