Domanda

Considera il seguente esempio minimo che riproduce un problema in un progetto molto più grande:

spec.h:
#include <iostream>

class A
{
public:
    template<typename T>
    T test(const std::string& a)
    {
        std::cout << "DEFAULT CALLED WITH " << a << "\n";
        return T();
    }
};
.

altro.cpp:
#include "spec.h"

template<>
float A::test<float>(const std::string& a)
{
    std::cout << "SPECIAL CALLED WITH " << a << "\n";
    return float();
}
.

spec.cpp:
#include <iostream>
#include "spec.h"

int main()
{
    A a;
    a.test<int>("int");
    a.test<float>("float");
    return 0;
}
.

Compilation:
$ make
rm -f *.o lib.a output
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
ar cr lib.a other.o
clang++ -g -o output lib.a spec.o
rm -f *.o output2
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
clang++ -g -o output2 other.o spec.o

$ ./output
DEFAULT CALLED WITH int
DEFAULT CALLED WITH float

$ ./output2
DEFAULT CALLED WITH int
SPECIAL CALLED WITH float
.

Domanda:

Perché è questo accadendo?è stato spogliato in qualche modo?Qual è la differenza tra lib.a e l'utilizzo del file dell'oggetto diretto?: -)

Grazie!

È stato utile?

Soluzione

Dalla Sezione 14.7.3p6:

.

Se un modello, un modello di membro o un membro di un modello di classe è esplicitamente specializzato quindi che la specializzazione deve essere dichiarata prima del primo utilizzo di tale specializzazione che causerebbe un'istanza implicita avrebbe avuto luogo, in ogni unità di traduzione in cui tale uso si verifica ; Nessuna diagnostica è richiesta. Se il programma non fornisce una definizione di una specializzazione esplicita e la specializzazione viene utilizzata in modo tale da provocare un'istanza implicita che si verifichi o il membro è una funzione membro virtuale, il programma è mal formato, nessuna diagnostica richiesta.

Il tuo programma è mal formato perché hai usato la specializzazione in spec.cpp senza dichiararlo prima in quella unità di traduzione. O, come dice il paragrafo seguente:

.

Il posizionamento delle dichiarazioni di specializzazione esplicita per modelli di funzionalità, modelli di classe, fluttuazioni di modelli di classe, dati di dati statici dei modelli di classe, classi membri di modelli di classe, enumerazioni dei membri dei modelli di classe, modelli di classe membro dei modelli di classe, funzione membro Modelli di modelli di classe, Funzioni dei membri dei modelli di elementi membri dei modelli di classe, Funzioni dei membri dei modelli dei membri delle classi non modelli, modelli di funzionalità del membro delle classi membri dei modelli di classe, ecc. E il collocamento di dichiarazioni parziali di specializzazione dei modelli di classe, membro Modelli di classe delle classi non modelli, modelli di classe membro dei modelli di classe, ecc., Può influenzare se un programma è ben formato secondo il relativo posizionamento delle dichiarazioni di specializzazione esplicita e dei loro punti di istanziazione nell'unità di traduzione come specificato sopra e sotto.

Quando si scrive una specializzazione, stai attento alla sua posizione;
o per farlo compilazione
sarà un simile processo per Kindle la sua auto-immolazione.

che voto per come l'awesomest paragrafo limerick in tutto lo standard .

Altri suggerimenti

La risposta di Ben Voigt è corretta, ma voglio aggiungerlo un po '.

Si stanno essenzialmente ottenendo due diverse versioni della funzione, una in altro. E uno in spec.o (generato dal modello in linea).Il linker è progettato per sceglierne uno e solo, facendo il presupposto che siano entrambi identici come lo richiede lo standard.Nel primo caso, il linker tirerà solo una definizione da una libreria se il simbolo non è già definito.Dal momento che è definito in Spec.o La definizione della biblioteca non viene utilizzata.

Con la definizione nell'intestazione ogni unità di traduzione può creare la propria istanziazione.Pertanto, non c'è mai un simbolo indefinito che fa riferimento alla tua versione specializzata.Corrispondentemente, il file oggetto con la versione specializzata non è incluso quando si guarda la libreria: non definisce alcun simbolo indefinito.Quando includente esplicitamente il file dell'oggetto durante il collegamento, il linker non ha altra scelta che includerlo.Tuttavia, è necessario dichiarare tutte le specializzazioni: senza la dichiarazione il compilatore non ha indizio che la versione generale non è applicabile.Cosa succede a questa versione, sia che venga utilizzata o meno, quindi, dipende dal modo in cui il simbolo viene trattato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top