2015-05-01 12 views
6

(domanda finale in basso)definizioni distinte di modelli variadic

Recentemente, ho chiesto a question riguardo a come avrei correggere errori del linker (sui simboli duplicati riguardanti più definizioni di un vuoto modello.

Perché Stavo usando le funzioni in più file sorgente, mi è stato suggerito di usare la parola chiave inline per consentire dichiarazioni nell'intestazione o mettere le dichiarazioni in un file sorgente compilato

Dopo aver capito che inline ha avuto alcune ripercussioni negative, ho inserito le mie dichiarazioni in un file sorgente.

Ora, questo andava bene, tranne che per i modelli variadic:

template<typename T, typename... Args> 
void cleanup(T *t, Args&&... args); 

ho trovato alcune soluzioni apparenti - ma non per i modelli variadic - utilizzare un file .tpp (ma ha cominciato dichiarando ancora una volta simboli duplicati) o mantenere il file sorgente e aggiungere istanze esplicite.

Ma il void cleanup ha il potenziale per essere utilizzato centinaia di combinazioni di parametri, quindi non voglio istanziare esplicitamente tutto.

Domanda: Così, come potrei fare per entrambi i

  1. Mantenere le definizioni variadic template nel file di origine o
  2. Mettere le definizioni in un file .tpp senza ottenere simboli duplicati, e in definitiva evitare di utilizzare inline?

Esempi di errori di simboli duplicati/non definiti per la dichiarazione .tpp e rispettivamente la definizione di modello sopra riportata in un file di origine.

duplicate symbol __Z7cleanupI10SDL_WindowJEEvPT_DpOT0_ in: 
    CMakeFiles/Game.dir/Game/main.cc.o 
    CMakeFiles/Game.dir/Game/RichTools/rtexture.cc.o 

_

Undefined symbols for architecture x86_64: 
    "void cleanup<SDL_Renderer, SDL_Window*&>(SDL_Renderer*, SDL_Window*&&&)", 
referenced from: 
cleanQuit() in main.cpp.o 
ld: symbol(s) not found for architecture x86_64 
+1

Si desidera che il compilatore di generare istanze quando vengono utilizzati, ma si desidera automaticamente scartare i duplicati? Usa 'inline' allora! Hai detto che hai considerato il suo uso ma che ha avuto "ripercussioni negative", ma quali sono esattamente? –

+0

Sembra che nella tua prima domanda tu non abbia capito la risposta. Il consiglio di rendere in linea o spostare il file sorgente riguardava solo le tue funzioni completamente specializzate - queste con il template elenco dei parametri vuoto <>. – PiotrNycz

risposta

2

Il consiglio in risposta alla tua prima domanda: per fare in linea o passare al file sorgente era solo circa le funzioni completamente specializzate - questi con elenco di parametri vuoto template <>.

Quindi, che:

Il file di intestazione:

// This shall be in header - it is not full specialization: 
template<typename T, typename... Args> 
void cleanup(T *t, Args&&... args){ 
    //Cleanup the first item in the list 
    cleanup(t); 
    //Recurse to clean up the remaining arguments 
    cleanup(std::forward<Args>(args)...); 
} 
// These shall be only declared here, and implemented in source file, 
// treat fully specialized function templates as regular functions 
template<> 
void cleanup<SDL_Window>(SDL_Window *win); 
template<> 
void cleanup<SDL_Renderer>(SDL_Renderer *ren); 
template<> 
void cleanup<SDL_Texture>(SDL_Texture *tex); 

il file sorgente:

template<> 
void cleanup<SDL_Window>(SDL_Window *win){ 
    if (!win){ 
     return; 
    } 
    SDL_DestroyWindow(win); 
} 
template<> 
void cleanup<SDL_Renderer>(SDL_Renderer *ren){ 
    if (!ren){ 
     return; 
    } 
    SDL_DestroyRenderer(ren); 
} 
template<> 
void cleanup<SDL_Texture>(SDL_Texture *tex){ 
    if (!tex){ 
     return; 
    } 
    SDL_DestroyTexture(tex); 
} 
template<> 
void cleanup<SDL_Surface>(SDL_Surface *surf){ 
    if (!surf){ 
     return; 
    } 
    SDL_FreeSurface(surf); 
} 
+0

Ma ciò significa che dovrei usare inline per la funzione "non specializzata", come ho provato prima. –

+0

@Hyperum perché la pensi così? Prova il mio consiglio.Per tutte le funzioni non completamente specializzate - devono solo essere nei file di intestazione e possono essere in linea o non in linea. C++ linker sta rimuovendo tali duplicati da solo - non devi preoccuparti. – PiotrNycz

+0

@Hyperium - esiste anche un metodo di istanziazione del template esplicito - ma come hai già osservato - è molto inconsueto da usare ... – PiotrNycz