嵌套类“未命名类型”

时间:2020-05-26 21:23:53

标签: c++ class scope nested declaration

我遇到以下错误:

main.cpp:18:5: error: 'Iterator' does not name a type
   18 |     Iterator begin() {
      |     ^~~~~~~~

使用以下代码:

#include <iostream>
#include <iostream>
#include <memory>
#include <fstream>
#include <filesystem>

using namespace std;

class Numbers {
    private:
    int current;
    int end;

    public:

    Numbers(int end) : current(0), end(end) {}

    Iterator begin() {
        return Iterator(this);
    }

    bool operator==(const Numbers& other) const {
        return current == other.current && end == other.end;
    }

    bool operator!=(const Numbers& other) const {
        return !(other == *this);
    }

    class Iterator {
        private:
        Numbers* range;

        public:
        using value_type = int;
        using difference_type = ptrdiff_t;
        using pointer = int*;
        using reference = int&;
        using iterator_category = input_iterator_tag;

        Iterator(Numbers* range) : range(range) {}

        int operator*() const {
            return range->current;
        }

        int* operator->() const {
            return &range->current;
        }

        bool operator==(const Iterator& other) const {
            return other.range == range;
        }

        bool operator!=(const Iterator& other) const {
            return !(*this == other);
        }

        Iterator& operator++() {
            range->current++;
            return *this;
        }


    };
};

事实证明,将begin函数移至嵌套的Iterator类下可以进行编译。

但这很奇怪-嵌套类不遵循与其他成员相同的访问规则,这意味着不需要前向引用吗?

我在网站上搜索了有关此确切问题的其他问题,似乎没有找到答案。

1 个答案:

答案 0 :(得分:2)

从评论到问题

也-我在成员函数中调用成员函数f没有问题 q其中,在q之后定义f。你能解释为什么后面的例子 与这个问题中描述的情况不同吗?

根据C ++ 20标准(11.4类成员)

6一个类的完整类上下文是一个

>(6.1)-功能主体(9.5.1),

(6.2)-默认参数(9.3.3.6)

(6.3)-noexcept-specifier(14.5)或

(6.4)—默认成员初始化程序

在类的成员规范内

因此,在完整的类上下文中,函数f的名称在函数q的主体内可见。

但是,内部类是在完整类上下文之外声明的。因此,根据C ++ 20标准(6.5.1非限定名称查找)

7定义X23之外的类中使用的名称。 X的完整类上下文(11.4)应在 通过以下方式:

>(7.1)-在X类中使用或成为X基类的成员之前 (11.8),或 ...

因此内部类Iterator的名称必须在用作成员函数的返回类型之前声明。

例如,您可以使用占位符auto作为返回类型,而不是名称Iterator。

auto begin() {
    return Iterator(this);
}