Skip to content

C++ Iterator

Brief

假如需要讓 A 可以被 for(auto ?: A) 使用, 就需要讓以下 code 是可以編譯的:

cpp
for (auto x = A.begin(); x != A.end(); ++x) {
}

所以我們會需要實做:

cpp
struct A {
	// A's implements' detail

	struct Iter {
		Iter& operator++();
		bool operator(const Iter& rhs) const;
	};

	Iter begin();
	Iter end();
};

Example

cpp
#include <iostream>

struct Range {
    // [l, r)
    int l = 0;
    int r = 100;

    struct Iter {
        int ptr = 0;

        int& operator*() {
            return ptr;
        }

        Iter& operator++() {
            ++ptr;
            return *this;
        }

        bool operator!=(const Iter& rhs) {
            return ptr != rhs.ptr;
        }
    };

    Iter begin() {
        return Iter{l};
    }

    Iter end() {
        return Iter{r};
    }
};

int main() {
    for (int i: Range()) {
        std::cout << i << std::endl;
    }
    return 0;
}

End 回傳的 ... 可以不同型別?

在某些情況下,我們沒辦法決定 Iter 之間是否相等,只能知道他是否已經結束了,例如 c++23 會出現的 std::generator 就用這個方式。

cpp
struct Iter {
	// ...

	// 直接判斷 Iter{nullptr} 有點髒,我去翻了一下網路上,看起來會去使用:
	// std::default_sentinel_t, 所以用了一樣的方式。
	// 這樣子 != 語意上就直接變成 “是不是結束”
	bool operator!=(const IterEnd &rhs) const {
		return !handle_.done();
	}
};

Iter begin() {
	return Iter{...};
}

IterEnd end() {
	return {};
}

Changelog

Just observe 👀