【一人 C++20 Advent Calendar 2019】範囲 for 文がカスタマイゼーションポイントを見つけるルールを緩和【3日目】
一人 C++20 Advent Calendar 2019 3日目の記事になります。
範囲 for 文がカスタマイゼーションポイントを見つけるルールを緩和
C++17 までは範囲 for で begin / end
を参照する場合に以下のような挙動になっていました。
begin() / end()
両方のメンバ関数を持っていればそれを使用するbegin() / end()
両方のメンバ関数を持っていなければ ADL で非メンバ関数のbegin() / end()
を参照するbegin()
もしくはend()
の片方のメンバ関数しか持ってない場合はエラーになる
この時に 3.
の挙動を緩和し『どちらか片方が定義されていなければ非メンバ関数の begin() / end()
を探しに行く』という挙動になります。
#include <iostream> #include <vector> // オレオレ range クラス struct range{ // int を counting するだけの iterator struct counting_iterator{ auto operator*() { return value; } auto operator ++() { return ++value; } auto operator !=(counting_iterator const& other) { return value != other.value; } int value; }; // begin ではなくて end だけ定義されている auto first() const { return counting_iterator { first_ }; } auto end() const { return counting_iterator { end_ }; } int first_, end_; }; // range-based for に対応させる為に後から begin 関数を用意する auto begin(range const& r) { return r.first(); } auto end(range const& r) { return r.end(); } int main(){ auto r1_10 = range{ 1, 10 }; // range は end() しか定義していないので C++17 ではエラーになる // C++20 では条件が緩和されているので動作する for(auto x : r1_10) { std::cout << x << std::endl; } return 0; } /* output: 1 2 3 4 5 6 7 8 9 */
上記の例でいえば range
クラスは end()
メンバ関数しか定義していないので C++17 ではエラーになりますが、C++20 では動作するようになります。
動作するようになるんですが手元で試してみたら C++17 でも動作しました。
参照しているサイトでも C++20 からって書いてあるんですがどういうことだろうか…C++ なにもわからない…
サポートコンパイラ?
- GCC 8