2

我有一个名为 的类A,在这个类中我有一个可迭代的容器,我通过遵循一些访问规则进行迭代——顺序、空虚和其他。

为了简化下面的示例,让我们考虑一下我只是在遍历容器,但这不能使用内置容器的 iterator来完成。

class A {
public:
    class iterator {
    public:
        // Constructor
        iterator() {
        }
        // Destructor
        ~iterator() {
        }
        // Advances the iterator
        void operator++() {
           // Some accessing policy
        }
    };
private:
    std::vector<int> a;
};

一切都非常好——而且看起来很整洁——除了,当我声明我的迭代器时,我必须使用typename——我几乎假设它是用来告诉编译器我拥有的是一个类型,而不是类实例本身。

问题:

  1. 为什么我必须使用typename

    A a;
    for (typename A::iterator it(...); it != ...; ++it) {
    }
    
  2. 迭代器通常如何定义,因为向量迭代器不需要typename标签?它是否与从类定义中声明向量而不是从向量本身有关?

    std::vector<int> v;
    for (std::vector<int>::iterator it(v.begin()); it != v.end(); ++it) {
    }
    
  3. 是否在容器类中定义了迭代器——我猜它被命名为组合——或者,如果没有,它是如何将迭代器添加到类的命名空间中的,例如:

    std::vector<int>::iterator it;
    
4

2 回答 2

4

1 - 为什么我必须使用typename:[...]

您不必使用typename. 当您使用从属的限定类型名称时,模板typename需要消歧器。StackOverflow 上的这个 Q&A 澄清了一些事情。这:

A a;
typename a::iterator it; // ERROR!

非法的 C++。如果这A不是模板参数的名称,您应该这样做:

A::iterator it;

如果你在一个模板里面并且A是一个模板参数的名字,比如在:

template<typename A>
struct X
{
    void foo()
    {
        typename A::iterator it;
    //  ^^^^^^^^
    //  This is necessary here!
    }
};

然后你必须使用typename告诉编译器后面的::是类型的名称。


2 - 迭代器通常如何定义,因为向量迭代器不需要typename标签?

同样,“向量迭代器不需要typename标签”是不正确的。如果您对该向量有明确的特化,例如:

std::vector<int>::iterator it; // "typename" not required

thentypename不是必需的,因为A::iterator it. 但是,如果您在以下情况下的模板中,则需要它:

template<typename A>
struct X
{
    void foo()
    {
        typename std::vector<A>::iterator it;
    //  ^^^^^^^^
    //  This is necessary here!
    }
};

那是因为std::vector<A>::iterator这里是一个限定的、依赖的类型名称。


3 - 是否在容器类中定义了迭代器——我猜它被命名为组合——或者,如果没有,它是如何将迭代器添加到类的命名空间中的,就像在 [..]

这可以通过定义一个嵌套类来完成,或者简单地通过使用类型别名来完成:

template<typename T>
struct X
{
    typedef T* iterator;
    iterator begin() { /* ... */ }
    // ...
};

X<int>::iterator it; // OK: "typename" not required

template<typename T>
void foo(X<T>& x)
{
    typename X<T>::iterator it = x.begin();
//  ^^^^^^^^
//  This is necessary here!

    // ...
}
于 2013-03-09T14:44:16.677 回答
1

您的示例代码存在很多问题,因此这可能是您正在寻找的答案(挥手):) 当然,如果您的示例不正确,那么所有的赌注都没有了。

我很惊讶这会起作用。'a' 是一个变量,'A' 是类。

此外,在使用默认构造函数声明变量时,不要使用结束括号 ()。

A a;
A::iterator it;
for (A::iterator it; it != ...; ++it) {
}

此外,迭代器是在容器类中定义的。只有在处理模板并且访问可以解释为静态成员或函数/嵌套类或 typedef 的内容时才需要使用 typename。可以通过 Andy Prowl 给出的答案进一步解释。

祝你好运

于 2013-03-09T15:19:29.240 回答