このページはC++20に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
C++17までは、範囲for文に指定するシーケンスの型がbegin
/end
メンバのどちらかでも持っていればbegin()
/end()
メンバ関数を使用し、どちらも持っていなければADLで非メンバ関数のbegin()
/end()
を探索する仕様となっていた。
C++20ではこのルールを緩和し、begin
/end
メンバの両方があるときに限りbegin()
/end()
メンバ関数を使用し、どちらかが不足していれば非メンバ関数のbegin()
/end()
を探しにいくよう改定する。
これは、begin
もしくはend
という何らかのメンバ (関数、変数、型) が特殊な意味を持ち、そのメンバが範囲for文で使用することを意図していないような状況に対応するための改訂である。
なお、この修正はC++11へ遡って適用された。そのため、この修正を実装した処理系では、以下のコンパイルエラーを試すことはできない。
例
#include <sstream>
#include <iterator>
struct X : std::stringstream {
X(const char* s)
: std::stringstream(s) {}
};
std::istream_iterator<char> begin(X& x)
{
return std::istream_iterator<char>(x);
}
std::istream_iterator<char> end(X&)
{
return std::istream_iterator<char>();
}
#include <iostream>
int main()
{
X x{"Hello"};
// P0962R1非対応の場合はコンパイルエラー
// (std::stringstream::endメンバだけが見つかり、対応するbeginがないというエラーになる)。
// P0962R1に対応していればOK
for (char c : x) {
std::cout << c << std::endl;
}
}
出力
H
e
l
l
o