2015-10-21 9 views
8

Utilizziamo il compilatore Intel C++ e rileviamo che compila (?) Quanto segue, ridotto da un uso di boost::function<Ponies()> f(unnamedNamespacedFunctor).I locals statici delle specializzazioni di template funzione con T = <classe namespace anonima> devono essere univoci?

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()); 
} 

Riga di comando:

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

La mia domanda è: è conforme? L'uso di locals statici in tali istanze genera un comportamento indefinito? Nell'ispezionare simboli prodotte, ho osservato che mentre f è trovi collegamento locale, come sospettavo, la variabile statica x riceve legame debole e quindi i due x 'es vengono fuse e diventa lotteria che viene scelto

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

Sarei grato per l'aiuto. Forse questo è in fin dei conti un bug del compilatore ed è già stato segnalato?

+0

si verifica anche se si rinomina uno dei 'struct A' per ad es. 'struct B'? –

+1

La definizione di 'f' non è in violazione dell'ODR? Cosa succede se metti le due definizioni di 'f' nei rispettivi namespace locali per correggere la violazione ODR? – MSalters

+0

@MSalters lo stesso accade con la funzione boost ::, che non posso cambiare così facilmente :) Se si tratta di una violazione ODR, immagino che sia contro la pratica esistente. Non ho trovato una regola che proibisca questo. Il collegamento dell'istanza del modello di funzione è esterno, ma il tipo di argomento ha un collegamento interno (e quindi è un tipo diverso in diverse TU!). Non riesco a trovare un paragrafo che lo impedisca e non sono sicuro che ci sia un motivo per vietarlo. –

risposta

2

Questo mi sembra un insetto. Lasciando A1 essere una delle esemplificazioni di A e A2 essere il contrario:

I presumere che la statica x ha legame debole in modo che il linker possibile unire copie della statica tra più copie dello stesso istanziazione. (Se sei riuscito a istanziare f<A1> in due diverse unità di traduzione, per esempio.)

In entrambi i f<A1> e f<A2> dovrebbe avere altro nome mangling, che causerebbe le due versioni della x avere nome diverso pressare (credo che alcuni compilatori realtà generare un valore casuale per rendere i nomi all'interno di spazi dei nomi anonimi unici, oppure x non dovrebbe avere il collegamento interno (poiché un tipo locale è stato utilizzato per creare un'istanza f, che dovrebbe rendere impossibile la replica in un'altra unità di traduzione).

Problemi correlati