2015-10-21 30 views
8

Intel C++ derleyicisini kullanıyoruz ve boost::function<Ponies()> f(unnamedNamespacedFunctor) kullanımından indirgenerek aşağıdakileri (?) Yanlış şekilde derlediğini tespit ettik.T = <adsız ad-sınıfı sınıf> ile işlev şablon uzmanlarının statik yerlileri benzersiz olmak için gerekli midir?

a1.cc:

template<typename T> 
int f(T) { static int x = T::x; return x; } 


namespace { struct A { static const int x = 1; }; } 

int f1() { 
    return f(A()); 
} 

a2.cc:

template<typename T> 
int f(T) { static int x = T::x; return x; } 


namespace { struct A { static const int x = 0; }; } 

int f2() { 
    return f(A()); 
} 

main.cc:

#include <cstdio> 

int f1(); 
int f2(); 

int main() { 
    std::printf("%d != %d\n", f1(), f2()); 
} 

Komut satırı:

# icpc a1.cc a2.cc main.cc -o main 
# ./main 
0 != 0 

Sorum şu: Bu uyumlu mu? Bu tür örneklemelerde durağan yerliler kullanıldığında tanımlanmamış davranışlar ortaya çıkıyor mu? üretilen semboller teftiş, ben tahmin ettiğim gibi x statik değişken zayıf bağlantıyı alır ve bu nedenle iki x 'es birleştirilir ve seçilir piyango olur f iken yerel bağının olduğunu belirtti

# icpc a2.cc a1.cc main.cc -o main 
# ./main 
1 != 1 

Yardım için minnettar olurum. Belki de bu aslında bir derleyici-hatadır ve daha önce bildirilmiştir?

+0

, bu aynı zamanda, struct A'lardan birini yeniden adlandırırsanız, bu da oluşur. Yapı B? –

+1

ODR'nin ihlali anlamında f değil midir? ODR ihlali gidermek için kendi yerel ad alanlarındaki iki f tanımı kullanılırsa ne olur? – MSalters

+0

@MSalters, aynı şeyi kolayca değiştiremediğim boost :: function ile gerçekleşir :) Eğer bir ODR ihlali ise, mevcut uygulamaya karşı olduğunu sanırım. Bunu yasaklayan bir kural bulamadım. İşlev şablonu örneğinin bağlantısı haricidir, ancak argüman türü iç bağlantıya sahiptir (ve dolayısıyla farklı TU'larda farklı bir tiptir!). Bunu yasaklayan bir paragraf bulamıyorum ve bunu yasaklamak için bir neden olduğundan emin değilim. –

cevap

2

Bu bana bir hata gibi görünüyor. A1 izin vermek A örneklemesi biri ve diğer olması A2:

I bağlayıcı aynı örnekleme çoklu kopyalarının arasında statik kopyalarını birleştirme böylece statik x zayıf zinciri olduğu tahmin. (Örneğin, iki farklı çeviri birimlerinde f<A1> örneğini başardı demektir.)

Ya f<A1> ve f<A2> bozma farklı isme sahip x iki versiyonu neden olacak olan, farklı ad bozma sahip olmalıdır (Ben aslında bazı derleyiciler düşünüyorum İsimsiz ad alanlarının isimlerini benzersiz hale getirmek için rastgele bir değer üretin) veya x'un iç bağlantısı olmamalıdır (çünkü yerel bir tür f'u başlatmak için kullanılmıştır, bu da başka bir çeviri biriminde çoğaltılmasını imkansız kılar).