2013-01-16 16 views
12

Bu bir derleyici-hata mı?Dünya çapında başka bir gizleme ad alanı kapsamındaki işleç

template <typename T> 
T& operator++(T& t) 
{ 
    return t; 
} 

namespace asdf { 

enum Foo { }; 
enum Bar { }; 

Foo& operator++(Foo& foo); 

void fun() 
{ 
    Bar bar; 
    ++bar; 
} 

} // end namespace asdf 

int main() 
{ 
    return 0; 
} 

GCC 4.7 hata iletisi şudur: bir hata değildir

Foo& operator++(Foo& foo); 
+1

[Evet edilir] (http://liveworkspace.org/code/2vreOi$0) .... –

+3

Sanmıyorum. VC++ aynı şeyi üretir. – SChepurin

+1

@KarthikT: Bağlantılı kodunuzun "bir hata" -argümenini nasıl desteklediğinden emin değilim. –

cevap

13

No: Eğer satırını açıklama ise

error: no match for 'operator++' in '++bar' 
note: candidate is: 
note: asdf::Foo& asdf::operator++(asdf::Foo&) 
note: no known conversion for argument 1 from 'asdf::Bar' to 'asdf::Foo&' 

O derler. Dikkate alınan üç paralel operatör kümesi vardır. Üyeler, üye olmayan operatörler ve yerleşikler.

üye olmayan olanları tüm sınıf üye fonksiyonları görmezden normal ADL + niteliksiz arama tarafından aranır. Bu nedenle, global operatör bir sözlükle daha yakın bir şekilde gizlenir (ve araya giren üye işlevi diğer üye olmayanları gizlemezdi).

Aşırı yük çözünürlüğünün adı sonra gerçekleştiğini unutmayın; Sizin durumunuzda operator++ ismi bulundu, ancak uygun bir aşırı yük yok.

Bar küresel ilan edilmişti, ve/veya (eski durumunda) ad asdf diğer operatör, ADL ya da (ikinci durumda) sıradan niteliksiz arama operatörü sürüklenen olsaydı

.


: Overload resolution (...) takes place after name lookup has succeeded. (C++ Standart)

+0

Bu yeterli ayrıntı olup olmadığından emin değilim. Eşleşme olmaması durumunda, bir sonraki kapalı alan adı mı bakılmamalıdır? –

+1

@phresnel: Peki, '++ ++' ismi, işleç ++ için bir eşleşmeyi nasıl oluşturur? Sadece isim araması sırasında alakalı olan * isimdir *. –

+0

@phresnel, aslında yerel bildirimler de kabul edilir. güncellenecek ... –

7

Resim bu bir derleyici hata değildir.

ifadesi ++bar için gerçekleştirilen olsun iki isim aramaları vardır. o operator++ ait ilk oluşumunu bulana kadar

  • düzenli ad arama çevreleyen kapsamları ve ad alanlarını arar. Bu arama dışarıda çalışır, böylece global isim alanı en son aranır. Operatör fonksiyonlarını ararken, üye fonksiyonları ayrı ayrı ele alınır (ve bu aramayı durdurmaz).
  • bağımsız ve bağımlı arama sonraki ve arama ilave sınıflar ve ad alanlarında başladı, ancak işlevi (bu durumda operator++) argümanları ile ilgili olanlar.

Sorudaki örnekte, normal arama asdf::operator++ bulur ve aramayı durdurur.
Bağımsız değişkene bağlı arama, için ilişkili ad alanı olduğundan, arama yapılacak yerlere yalnızca asdf ad alanını ekler. Bu nedenle, küresel operator++ bulunamıyor.

Sen küresel operator++ ad asdf bir kullanarak bildiriyle bulunabilir yapabilirsiniz.

+0

Tanımladığınız ilk mermi, sınıf kapsamlarını dikkate almaz. Yani, bir sınıf üyesi işlevinde bir işleç ifadesi kullansanız bile, aynı adda bir üye operatör olmasına rağmen, ad alanı kapsamı operatörü, adsız olmayan bir ad alanı kapsamında bile bulunabilir. –

+0

@ JohannesSchaub-litb: Bu, C++ 03 ve C++ 11 arasında bir değişiklik mi? Çünkü C++ 03 madde 3.4.1'de [basic.lookup.unqual] böyle bir istisna bulamıyorum. –

+1

kurallar 13.3.1.2'de belirtilmiştir :-) –

1

sadece aşırı yüklenmesi aynı kapsamda içinde tanımlanan adları için de geçerlidir. Derleyici eşleşen bir ad bulduğunda, bulduğu ad kullanılamayan bir şeye uygulansa bile, dış kapsamlarda görünmez. Bunun operatörlerle ilgisi yok; Kod, işleç adını, işleçsel ++ kullandığı şekilde kullandıysa, aynı hatayı alır.Örneğin:

void f(int); 

struct C { 
void f(const C&); 
void g() { 
    f(3); // error: f(const C&) can't be called with argument 3 
};