C ++类迭代器实用程序:定义和用法

时间:2013-03-09 14:33:28

标签: c++ class templates iterator typename

我有一个名为A的类,在这个类中我有一个可迭代的容器,我会通过遵循一些访问规则来迭代 - 顺序,空白和其他。

为简化以下示例,我们假设我只是在容器中进行迭代,但不能使用内置容器的迭代器来完成。

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;
    

2 个答案:

答案 0 :(得分:4)

  

1 - 当我这样做时,为什么必须使用typename:[...]

您不必使用typename。当您使用依赖的限定类型名称时,typename消歧器在模板内 This Q&A on StackOverflow clarifies things。这个:

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

然后typename不是必需的,因为A::iterator it中不需要template<typename A> struct X { void foo() { typename std::vector<A>::iterator it; // ^^^^^^^^ // This is necessary here! } }; 。但是,如果您在模板中,如下例所示,则需要:

std::vector<A>::iterator

这是因为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! // ... } 这里是一个合格的依赖类型名称。


  

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

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

{{1}}

答案 1 :(得分:1)

你的示例代码有很多问题,所以这可能是你正在寻找的答案( wave hand ):)当然如果你的例子不正确,那么所有的赌注都是关闭。

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

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

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

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

祝你好运