Bjarne bu ADL örneği hakkında yanılıyor mu, yoksa benim bir derleyici hatası mı var?


81

The C ++ Programming Language, 4th Edition ( Bjarne Stroustrup tarafından ) hakkında okuyorum. İşte alıntı (26.3.6, Aşırı agresif ADL):

Bağımsız değişkene bağlı arama (genellikle ADL olarak adlandırılır) ayrıntılardan kaçınmak için çok kullanışlıdır (14.2.4). Örneğin:

#include <iostream>

int main()
{
    std::cout << "Hello, world" << endl; // OK because of ADL
}

Bağımsız değişkene bağlı arama olmadan endlmanipülatör bulunamazdı. İlk bağımsız değişken için bu, derleyici ilan olduğu <<bir olduğu ostreamtanımlanmıştır std. Bu nedenle, arar endliçinde stdve onu (içinde bulur <iostream>).

Ve derleyici tarafından üretilen sonuç şu şekildedir (C ++ 11 modu):

prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
 std::cout << "Hello, world" << endl;
                                ^

Bu ya derleyicideki ya da kitaptaki bir hatadır. Standart ne diyor?

Güncelleme:

Biraz netleştirmem gerekiyor. Doğru cevabın kullanmak olduğunu biliyorum std::endl. Soru kitaptaki metinle ilgiliydi. As Lachlan Easton zaten bu sadece bir yazım hatası değil, dedi. Bütün paragraf (muhtemelen) yanlış. Kitap başka (daha az bilinen) bir yazara aitse bu tür bir hatayı kabul edebilirim, ancak Bjarne tarafından yazıldığı için şüpheliydim (ve hala da öyleyim).


12
std::endlhata yok
aaronman

3
Deneyimlerime göre, kitaplar hatalar ve yazım hataları ile ünlüdür. Umarım iyi bir kitapta sadece küçük / açık.
Neil Kirk

31
@aaronman OP açıkça bunun farkında. Alıntıdan, Bjarne'nin (C ++ yaratıcısı)std:: ADL nedeniyle bu durumda gerekli olmadığını iddia ettiği anlaşılıyor . Ama bu derlemez, dolayısıyla soru.
BlueRaja - Dany Pflughoeft

6
Evet, mesele şu ki, kitap açıkça yanlış şeyi söylüyor. Bu bir yazım hatası değil, aslında neyin doğru olmadığını açıklamak için bütün bir paragraf yazıldı. Kitaptaki bir böcek.
DanielKO

7
@maverik O olduğu kitapta bir hata. Bu konuyu birkaç dakika önce kendisine bildirmiştim, cevabını size bildireceğim.
Ali

Yanıtlar:


83

Derleyicide bir hata değil. ADL arama için kullanılan işlevleri değil bağımsız değişkenleri . operator<<ADL aracılığıyla burada parametrelere std::coutve (ne olması gerektiğine) bakarak bulunan işlevdir std::endl.


2
Aslında, geriye dönüp bakıldığında bu std::endl, aslında (ve kafa karıştırıcı) bir işlev olan gerçeği kullanarak kodu geçerli endl(std::cout << "Hello, world"); // OK because of ADL
kılmanın bir yolunu gösteriyor

49

Bunun bir yazım hatası olduğunu söyleyenler için değil. Ya Bjarne bir hata yaptı ya da derleyici yanlış yaptı. OP tarafından yayınlanan paragraftan sonraki paragraf okur

Bağımsız değişkene bağlı arama olmadan, endl işleyicisi bulunamazdı. Olduğu gibi, derleyici << için ilk bağımsız değişkenin std'de tanımlanan bir ostream olduğunu fark eder. Bu nedenle, std'de endl'yi arar ve bulur (içinde <iostream>).


18
Görünüşe göre bayım, kitabı kitapta okuyan tek kişi sizsiniz. Bu ya dil kurallarında önemli bir değişiklik, tüm mevcut C ++ derleyicileri standart dışı hale getiriyor (C ++ 11 için) ya da Bay Stroustrup'tan göze çarpan bir hata (ve sadece bir yazım hatası değil). Revize edilmiş bir baskı almak için fazladan iki ay beklemeyi tercih ederdim. Sakalını geri uzatsa iyi olur.
DanielKO

Bu arada, işaretleme alıntıdaki son biti yedi, muhtemelen "(in <iostream>) " geri işaretlerini kullanmak istersiniz .
DanielKO

20

Diğerlerinin daha önce de belirttiği gibi kitapta bir yazım hatası var. Ancak, kitapta kastedilen, yazmak zorunda olduğumuzdur.

std::operator<<(std::cout, "Hello, world").operator<<(std::endl);

ADL olmadan. Bjarne'ın ayrıntıyla kastettiği buydu.


Düzeltilmiş durumdayım. As Lachlan Easton işaret, bir yazım hatası ama değil hata kitapta. Bu kitaba erişimim yok, bu yüzden o paragrafı okuyup kendim fark edemedim. Bu hatayı Bjarne'ye bildirdim ki düzeltebilsin.


Komik. Aynı örnek Wikipedia'da ve

Bunun std::endlbir işlev olduğunu , ancak bir argüman olarak kullanıldığından tam nitelendirilmesi gerektiğini unutmayın operator<<( std::endlbir işlev çağrısı değil, bir işlev göstericisidir).

Hiç şüphe yok ki kitaptaki bir hatadır. Yine de örnek std::operator<<(std::cout, "Hello, world").operator<<(std::endl);, ADL'nin ayrıntıyı azaltmaya nasıl yardımcı olduğunu gösterir.


Gx_'ye hatamı işaret ettiği için teşekkürler .


Bu bir yazım hatasından daha fazlasıydı, bir şeyler düşündü (aramanın nasıl std::operator<<gerçekleştiğini) ve yanlış bilgilerle bütün bir paragraf yazdı. ADL kurallarının değiştiğine ve derleyicilerin artık bozuk olduğuna gerçekten inanmanızı sağlıyor.
DanielKO

aslında kitapta epeyce yazım hatası var gibi görünüyor, örn. 17.2.5
AndersK

@DanielKO Düzeltilmiş durumdayım; Cevabımı düzelttim, teşekkürler. Bu kitaba erişimim yok, bu yüzden yazım hatası olduğunu düşündüm. Her durumda, ADL ayrıntı düzeyini azaltmaya yardımcı oluyor ve verdiğim kod buna bir örnek. Her durumda, söylediğin için teşekkürler.
Ali

Aslında ne biz gerçekten yazmak zorunda kalacak olan std::operator<<(std::cout, "Hello, world").operator<<(std::endl);(bkz üye olmayanoperator<< ve üyeoperator<< )
gx_

10

İpucu, "bağımsız değişkene bağlı arama" adındadır.

Bağımsız değişkenlere bağlı olarak çalışan, nitelenmemiş işlev adlarının aranmasıdır .

Bu arama ile ilgisi var için argümanlar.

Bjarne yanlış söyledi.


8

Kitabım yok, ancak bu kitapta bir hata gibi görünüyor, ad alanı niteleyicisinin eksik olmasının ADL ile hiçbir ilgisi yok. Olmalı std::endl.


1
Katılıyorum. Ama bu oldukça tuhaf bir ifade (kitaptaki ifadeyi kastediyorum). Umarım Bjarne bunu bilmelidir.
maverik

@maverik Belki zaten biliyordur, birinin bunu bildirmesine şaşırmam. Değilse, yapabilirsin :)
Borgleader

@maverik bu sadece bir yazım hatası, sanırım başka biri bunu fark etti
aaronman

2
Evet, gerçekten, tüm ifadeyi yanlış anladım (ile std::cout) O aramaktan bahsediyordu operator<<, değil endl.
maverik

4

Evet, bu bir hatadır - örnek biçimsizdir ve derlenmemelidir. ADL, işlev çağrısı ifadelerini tanıtan niteliksiz işlev adlarına uygulanır. endlarama yapmaya çalışan bir id ifadesidir std::endl. endlbir işlev çağrısı ifadesi sunmaz, bu nedenle bağımsız değişkene bağlı arama onun için kullanılmaz, yalnızca niteliksiz arama kullanılır, bu nedenle std::endlamaçlandığı gibi bulmaz .

Daha basit ve doğru bir örnek şöyle olabilir:

#include <vector>

int main()
{
    std::vector<int> x, y;
    swap(x,y); // calls std::swap due to ADL
}

Özetle, f(x,y,z)nitelenmemiş bir id (ör. f) İle bir işlev çağrısı (ör. ) Aranmadan önce, önce işlevin parametreleri (ör.x,y,z ), Tiplerini belirlemek için analiz edilir. Türlere göre ilişkili ad alanlarının bir listesi oluşturulur (örneğin, türün tanımının çevreleyen ad alanı, ilişkili bir ad alanıdır). Bu ad alanları daha sonra işlev için ek olarak aranır.

Bjarne'nin örneğinin amacı, std::operator<<işlevin ADL'sini göstermektir , değil std::endl. Bu nedenle aşırı operatörler, aslında işlev çağrısı ifadelerde olduğu ilave bir anlayış gerektirir x << yaraçlar operator<<(x,y)ve operator<<bir niteliksiz adıdır ve bu nedenle ADL buna geçerlidir. LHS'nin türüdür std::ostreamböylece stdbağlantılı bir ad ve bu nedenle std::operator<<(ostream&, ...)bulunmaktadır.

Düzeltilmiş yorum şu şekilde olmalıdır:

Bağımsız değişkene bağlı arama olmadan <<, stdad alanındaki aşırı yüklenmiş operatör bulunamazdı. Olduğu gibi, derleyici << için ilk bağımsız değişkenin std'de tanımlanan bir ostream olduğunu fark eder. Bu nedenle, operatörü <<std'de arar ve bulur (içinde <iostream>).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.