Soru (ve çoğu cevap) bu hata raporunun çözümünde gönderildiği için standart değiştirildi .
Bir for(:)
döngüyü türünüzde çalıştırmanın X
yolu artık iki yoldan biridir:
Ve const
varyasyonlar için benzer . Bu, hem hata raporu değişikliklerini uygulayan derleyiciler hem de yapmayan derleyiciler üzerinde çalışır.
Döndürülen nesnelerin aslında yineleyici olması gerekmez. for(:)
Döngü, C ++ standart birçok yerinde farklı olarak bir şey eşdeğer genişletmek için belirtilen :
for( range_declaration : range_expression )
dönüşür:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
ile başlayan değişkenler nerede __
sadece fuar için vardır ve begin_expr
ve end_expr
sihirli olduğuna çağrılar begin
/ end
.²
Başlangıç / bitiş dönüş değeriyle ilgili gereksinimler basittir: Önceden aşırı yükleme yapmalı ++
, başlatma ifadelerinin geçerli olduğundan, !=
bir boole bağlamında kullanılabilecek ikili *
, atayabileceğiniz / başlatabileceğiniz bir şeyi döndüren tekli range_declaration
ve herkese açık olarak göstermelisiniz yıkıcı.
Bunu yineleyici ile uyumlu olmayan bir şekilde yapmak, muhtemelen kötü bir fikirdir, çünkü C ++ 'ın gelecekteki yinelemeleri, kodunuzu kırmak konusunda nispeten daha tehlikeli olabilir.
Bir yana, standardın gelecekteki bir revizyonunun bundan end_expr
farklı bir tür döndürmesine izin vermesi makul bir olasılıktır begin_expr
. Bu, elle yazılmış bir C döngüsü kadar verimli olacak şekilde optimize edilmesi kolay "tembel sonlandırma tespiti gibi" ve diğer benzer avantajlara izin verdiği için faydalıdır.
Lo for(:)
Döngülerin geçici bir auto&&
değişkeni sakladığını ve bunu size değer olarak ilettiğini unutmayın. Geçici (veya başka bir değer) üzerinden yineleme yapıp yapmadığınızı algılayamazsınız; böyle bir aşırı yük bir for(:)
döngü tarafından çağrılmaz . Bkz. N4527'den [stmt.ranged] 1.2-1.3.
² çağrı Ya begin
/ end
yöntemini veya ADL okunur arama serbest fonksiyonu begin
/ end
, veya C tarzı dizi destek için büyü. Aynı tipte veya std::begin
ona bağımlı range_expression
bir nesne döndürmediği sürece çağrılmadığını unutmayın namespace std
.
İçinde c ++ 17 for-for ifadesi güncellendi
{
auto && __range = range_expression ;
auto __begin = begin_expr;
auto __end = end_expr;
for (;__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
__begin
ve __end
ayrıştırılmış türleri ile .
Bu, son yineleyicinin start ile aynı tipte olmamasına izin verir. Bitiş yineleyici türünüz, yalnızca başlangıç !=
yineleyici türüyle desteklenen bir "sentinel" olabilir .
Bunun neden faydalı olduğuna dair pratik bir örnek, son yinelemenizin a ile " char*
işaret edip etmediğini kontrol etmek" i okuyabilmesidir . Bu, bir C ++ aralığı-for ifadesinin, boş sonlandırılmış bir arabellek üzerinden yineleme yaparken en uygun kodu üretmesini sağlar .'0'
==
char*
char*
struct null_sentinal_t {
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator==(Rhs const& ptr, null_sentinal_t) {
return !*ptr;
}
template<class Rhs,
std::enable_if_t<!std::is_same<Rhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(Rhs const& ptr, null_sentinal_t) {
return !(ptr==null_sentinal_t{});
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator==(null_sentinal_t, Lhs const& ptr) {
return !*ptr;
}
template<class Lhs,
std::enable_if_t<!std::is_same<Lhs, null_sentinal_t>{},int> =0
>
friend bool operator!=(null_sentinal_t, Lhs const& ptr) {
return !(null_sentinal_t{}==ptr);
}
friend bool operator==(null_sentinal_t, null_sentinal_t) {
return true;
}
friend bool operator!=(null_sentinal_t, null_sentinal_t) {
return false;
}
};
tam C ++ 17 desteği olmayan bir derleyicide canlı örnek ; for
döngü elle genişletildi.
begin/end
veya bir arkadaşı tanımlayarak , statik veya serbest olarak mümkündürbegin/end
. Ücretsiz isim koyduğunuz ad alanına dikkat edin: stackoverflow.com/questions/28242073/…