2015-11-06 25 views
7

Aşağıdaki kodisim araması GNU derleyicisinde buggy mi?

#include <iostream> 

typedef double A; // a global typedef 

template <class Z> struct B // a template class... 
{ 
    A i{22.2}; // global typedef is in scope 
    typedef int A; // now a local typedef with the same name is introduced 
    A b{24}; // now the local typedef is in scope 
    Z c{36}; // a simple member of the template type 
}; 

template <class Z> struct C : B<Z> // a template struct inheriting B 
{ 
    A a; // global typedef is in scope because we are in a template struct 
    C() : a(2.2){ } 
}; 

int main() 
{ 
    C<int> c; 
    std::cout << "c's members: " 
      << c.a << ' ' 
      << c.i << ' ' 
      << c.b << ' ' 
      << c.c << std::endl; 
    std::cout << "their sizeof: " 
      << sizeof(c.a) << ' ' 
      << sizeof(c.i) << ' ' 
      << sizeof(c.b) << ' ' 
      << sizeof(c.c) << std::endl; 
} 

o clang 3.5.0 gereğidir ve gömülü yorumlarda açıklamaya çalıştığım gibi davranır ise GNU-g++ 4.9.2 tarafından derlenen ve çıkış tarafından görülebileceği gibi üretilen DEĞİLDİR. Bu GNU derleyicisindeki bir hata mı? tanı arama kapsamında clang tarafından gerçekleştirilen hiyerarşi template yapılmış olmadığını struct B

error: changes meaning of ‘A’ from ‘typedef double A’

Not kapsamında hat typedef int A; (ve tabii Z c{36}; beyan kaldırılır) diyor C (doğru olarak, sanırım) 'u B kapsamında bulur ve a'untip int; o zaman standart taslak (N4140) C++ itibaren başlatılıyor double sabit 2.2 daralması hakkında bir uyarı ...

+0

Benzer [[Sürüm adı ile sınıf adı adının bir dış adı gölgelemesi arasındaki etkileşim] (http://stackoverflow.com/q/26681873/1708801) –

+0

Bu kodu uygun şekilde biçimlendirebilir ve kısaltabilir misiniz? – Columbo

+0

Garip girinti nedir? –

cevap

9

§3.3.7 [basic.scope.class]

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

sorunları

A i{22.2}, başlangıçta genel ::A anlamına gelir. Ancak, B'un tamamlanmış kapsamı içinde yeniden değerlendirildiğinde, B::A bildirildikten sonra, B::A anlamına gelir. Bu, yukarıdaki kuralı ihlal ediyor.

Düzeltmek için, tam nitelikli adı kullanın: ::A i{22.2}. ::A her zaman B::A bildirildikten sonra bile global A anlamına gelir, dolayısıyla kuralı ihlal etmez.

Bu g ++ dosyasında bir hata değil; Bu sadece kötü biçimlenmiş bir program. Derleyicinin kural ihlali için size bir teşhis vermesi gerekmez, ancak bunu kabul etmek de gerekmez.