Утилита итератора класса C ++: определение и использование

У меня есть класс с именем 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

Решение

1 — почему я должен использовать typename когда я делаю: […]

Вам не нужно использовать typename, typename требуется устранение неоднозначности внутри шаблон, когда вы используете зависимое, полное имя типа. Это Q&А на StackOverflow проясняет вещи. Это:

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 тегMsgstr «Если у вас есть явная специализация этого вектора, например:

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 Вот полное имя зависимого типа.


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!

// ...
}
4

Другие решения

Есть много проблем с вашим примером кода, так что это может быть ответ, который вы ищете (машет рукой) 🙂 Конечно, если ваши примеры не верны, то все ставки сняты.

Я удивлен, что это сработает вообще. «a» — это переменная, «A» — это класс.

Кроме того, при объявлении переменной конструктором по умолчанию вы не используете завершающие скобки ().

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

Кроме того, итераторы определены в классе контейнера. Использование typename необходимо только тогда, когда вы имеете дело с шаблонами и только при доступе к чему-то, что может быть интерпретировано как статический член или класс function / nested или typedef. Это может быть дополнительно объяснено ответом Вот который также дал Энди Проул.

Удачи

1

По вопросам рекламы [email protected]