Soru Derleyicinin ad alanlarıyla ilginç davranışı


Aşağıdaki kodu varsayalım:

#include <iostream>
using namespace std;

namespace X
{
  class A{};

  void f(A a){}

  void g(int a){}
}

int main()
{
  X::A a;
  f(a);
  g(5);
}

Kodu derlediğimde, aşağıdaki derleme hatası oluşur:

main.cpp: 'int main ()' işlevinde:
  main.cpp: hata: 'g' bu kapsamda bildirilmedi

Yani işlev f mükemmel bir şekilde derlenmiştir, ancak g değil. Nasıl? Her ikisi de aynı isim alanına aittir. Derleyici bu işlevi anlar mı f aittir X türün argümanından ad alanı X::A? Derleyici böyle durumlarda nasıl davranır?


32
2017-09-22 14:14


Menşei




Cevaplar:


Bu işlev çağrısı ifadesi için çalışır:

f(a);

çünkü ad alanı X::A ait olduğu işleve aittir f Nedeniyle bağımsız değişken bağımlı aramaADL), cppreference açıklıyor ADL aşağıdaki gibi:

Ayrıca ADL veya Koenig arama olarak bilinen bağımsız değişken arama,   içinde niteliksiz fonksiyon isimlerini aramak için kurallar seti   örtülü işlev çağrıları da dahil olmak üzere işlev çağrısı ifadeleri   aşırı yüklenen operatörler. Bu işlev isimleri   kapsamları ve ad alanlarına ek olarak kendi argümanlarının ad alanları   olağan niteliksiz isim aramasıyla değerlendirilir.

Bağımsız değişkene bağlı arama, tanımlanan operatörlerin kullanılmasını sağlar   farklı bir ad alanında

Bu kaplıdır taslak C ++ standardı Bölüm 3.4.2  Bağımsız değişkene bağımlı arama:

Bir postfix ifadesi ne zaman işlev çağrısı (5.2.2) bir niteliksiz kimliktir, dikkate alınmayan diğer ad alanları   olağan vasıfsız arama sırasında (3.4.1) aranabilir, ve bu ad alanlarında, ad alanı-kapsamı   Arkadaş fonksiyonu veya işlev şablonu bildirimleri (11.3) başka türlü görülemez

ve söylemeye devam ediyor:

Her biri için işlev çağrısında T türünde argüman, sıfır veya daha fazla ilişkili ad alanı kümesi var ve bir   Dikkate alınacak sıfır veya daha fazla ilişkili sınıf kümesi. İsim ve sınıf kümeleri belirlenir.   tamamen işlev argümanlarının türlerine (ve herhangi bir şablon şablonu argümanının isim alanına).

ve aşağıdaki mermi içerir:

Eğer T bir sınıf tipi (sendikalar dahil) ise, onun ilişkili sınıfları şunlardır: sınıfın kendisi; bunun bir sınıfı   Üye, varsa; ve doğrudan ve dolaylı temel sınıfları. İlişkili ad alanları ad alanlarıdır.   onun ilişkili sınıfları üyeleridir. [...]

ve daha sonra aşağı sizin sorununuza benzer bir örnek sağlar:

namespace NS {
  class T { };
  void f(T);
  void g(T, int);
}

NS::T parm;
void g(NS::T, float);

int main() {
  f(parm); // OK: calls NS::f
  extern void g(NS::T, float);
  g(parm, 1); // OK: calls g(NS::T, float)
}

İşlev çağrısı ifadesi:

g(5);

çalışmıyor çünkü ADL Temel türler olan argümanlar için herhangi bir isim alanı eklemez.

Herb Sutter, ADL'yi kapsar # 30 ve Sınıfta Neler Var? - Arayüz İlkesi.


19
2017-09-22 14:24



does extern örnekte herhangi bir şeyi etkiler mi? - 0x499602D2
@dyp ugh, bunu işaret ettiğin için teşekkür ederim, keşke herkesin cevabını okuduğunda herkesin gözlemci olmasını isterdim. - Shafik Yaghmour
Her zaman cevaplarınızı okumakla ilgileniyorum, çünkü bunlar genellikle çok kapsamlı ve çok çeşitli kaynaklar kullanıyorsunuz. İlk cümleyi ilk bakışta anlamakta bazı sıkıntılar yaşadım (bildiğiniz gibi, intro genellikle basit bir özet / genel bakış). - dyp
@dyp C ++ benim işim ve yapmayı sevdiğim şey, bu yüzden kapsamlı cevaplar yazmak beni dürüst ve öğrenmeye devam ediyor. Her zaman harika bir iş yapmam, ancak yapıcı geri bildirimlere dayanarak iyileştirmeler yapmaktan mutluluk duyuyorum. - Shafik Yaghmour
@ 0x499602D2 böylece extern sonucu etkilemez, g dolaylı olarak extern ama yerel beyannamesi g önemli. Dün gerçekten çok yavaş olmalıydım, bu sabah çok hızlı çalışmasının nedenini anladım. - Shafik Yaghmour


X::A a;
f(a);

nedeniyle çalışıyor Bağımsız değişkene bağlı arama (Koenig Lookup olarak da bilinir). a sınıfın bir nesnesidir Aad alanı içinde XDerleyici eş anlamlı özellikli bir işlevi ararken f, isim alanına bakacak X bu durumda. Görmek Bağımsız Değişkene Bağımlı Arama daha fazla bilgi için.


27
2017-09-22 14:17



Yani bu yüzden std :: öneki gerekeceğini düşündüğümde çekildiğini görüyorum. Temiz. - Captain Giraffe


Kod ne zaman f(a), derleyici işlevi bulur void f(A a){} içinde namespace X yüzünden ADL (bağımsız değişken bağımlı arama olarak da bilinir) Koenig yukarı Bak).

A ad alanında bildirildi Xdolayısıyla derleyicinin tanımına bakması gerektiğinde fnesneden dolayı bu ad alanından olasılıklar içerir a türü A bu ad alanında (beyan edildiği gibi) X::A a;).

Diğer yandan, int içinde bildirilmemiş namespace X, Böylece namespace X aramaya dahil değildir. İçin uygun bir işlev olmadığından f bulunur, derlenemez.


6
2017-09-22 14:16



ADL nedir? - randomusername
Bağımsız değişken bağımlı arama - Niall