2015-09-06 18 views
10

Dopo la mia scoperta di incompatibilità tra MSVC e GCC (probabilmente anche clang) nella compilazione e nel collegamento dello stesso codice, sono curioso che questo programma venga effettivamente compilato e collegato e quindi sia un bug in MSVC (che riporta un errore del linker) o dovrei scrivere diversamente. Il programma consiste di 3 file:Il seguente programma deve essere compilato secondo lo standard?

Ch

template <typename T> 
struct A 
{ 
    void func() {}; 
}; 

template <> 
void A<int>::func(); 

A.cpp:

#include "C.h" 
int main() 
{ 
    A<int> x; 
    x.func(); 
} 

B.cpp:

#include "C.h" 
template <> 
void A<int>::func() 
{ 
} 

L'errore di linker risultante da MSVC è:

A.OBJ: LNK2019 di errore: simbolo esterno non risolto "public: void __thiscall A :: func (void)"

Quindi, in pratica si decide di non creare il simbolo di definizione posto in B.cpp. La cosa che mi fa fortemente sospettare che sia un bug è che spostare la definizione non specificata di func dalla definizione della struct e persino posizionarla sopra la dichiarazione di specializzazione rende il linnking del programma riuscito, ma mi piacerebbe esserne sicuro.

Quindi la mia domanda è: questo programma dovrebbe essere compilato e collegato senza errori da un compilatore/linker conforme?

+0

Sembra un insetto per me. Stai usando l'ultima versione (2015) di MSVC? –

+0

@MatsPetersson Sì, 2015. – Predelnik

+0

Il codice viene compilato bene anche con clang ++.È un po 'strano, dal momento che essenzialmente stai fornendo due definizioni per 'func' - Non sono abbastanza un avvocato della lingua per dire se è corretto o meno (penso che lo sia) –

risposta

1

dalla norma:

© ISO/IEC N4527 14.6.4.1 Punto di esemplificazione [temp.point] 1 Per una specializzazione di modello di funzione, un modello di specializzazione funzione membro, o di una specializzazione per un membro funzione o membro dati statici di un modello di classe , se la specializzazione è implicitamente istanziata perché è referenziato da all'interno di un'altra specializzazione del modello e il contesto da cui viene fatto riferimento dipende da un parametro di modello, il punto di istanziazione del la specializzazione è il poi nt di esemplificazione della specializzazione allegata. Altrimenti, il punto di istanziazione per tale specializzazione segue immediatamente la dichiarazione o la definizione dell'ambito dello spazio dei nomi che fa riferimento alla specializzazione .

In questo caso pare ciò significa in C.h dove avviene la "dichiarazione portata". Se questo è il caso, il tuo codice dovrebbe collegarsi a una catena di strumenti conforme allo standard. Potrei interpretare erroneamente questo ...

-2

Gli spazi dei nomi senza nome hanno un collegamento interno. Poiché la specializzazione del modello si trova all'interno di uno spazio dei nomi senza nome, ha anche un collegamento interno.

Per risolvere il problema, inserire il modello in uno spazio dei nomi denominato o specificare la specializzazione come "esterno".

+0

"namespace senza nome" non significa quello che sembra che pensi significhi. –

Problemi correlati