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?
si verifica anche se si rinomina uno dei 'struct A' per ad es. 'struct B'? –
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
@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. –