2015-04-29 13 views
7

(Mac)C++ zduplikowane symbole

próbowałem nazw, w tym strażników pragmy raz, itd

Zasadniczo, jest to struktura:

CMakeLists.txt

add_executable(Game Game/main.cpp Game/rtexture.cpp) 

Gra/main.cpp

#include "cleanup.h" 

//... 
cleanup(foobar); 

gier/rtexture.cpp

#include "cleanup.h" 

//... 
cleanup(foobar); 

cleanup.h

//various includes 

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 specializations serve to free the passed argument and also provide the 
* base cases for the recursive call above, eg. when args is only a single item 
* one of the specializations below will be called by 
* Cleanup(std::forward<Args>(args)...), ending the recursion 
* We also make it safe to pass nullptrs to handle situations where we 
* don't want to bother finding out which values failed to load (and thus are null) 
* but rather just want to clean everything up and let cleanup sort it out 
*/ 
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); 
} 

Jeśli ktoś pyta, ja wziąłem ten „cleanup.h” od samouczka, ale nie może znaleźć drogę do włączenia go w wiele klas bez deklarowania duplikatów symboli.

Home at cruz45488-y19-MBA13-12 in ~/desktop/sdlworkspace/tmp 
$ make 
Linking CXX executable Game 
duplicate symbol __ZN5RUtil7cleanupI10SDL_WindowJEEEvPT_DpOT0_ in: 
    CMakeFiles/Game.dir/Game/main.cpp.o 
    CMakeFiles/Game.dir/Game/rtexture.cpp.o 
duplicate symbol __ZN5RUtil7cleanupI12SDL_RendererJEEEvPT_DpOT0_ in: 
    CMakeFiles/Game.dir/Game/main.cpp.o 
    CMakeFiles/Game.dir/Game/rtexture.cpp.o 
duplicate symbol __ZN5RUtil7cleanupI11SDL_TextureJEEEvPT_DpOT0_ in: 
    CMakeFiles/Game.dir/Game/main.cpp.o 
    CMakeFiles/Game.dir/Game/rtexture.cpp.o 
duplicate symbol __ZN5RUtil7cleanupI11SDL_SurfaceJEEEvPT_DpOT0_ in: 
    CMakeFiles/Game.dir/Game/main.cpp.o 
    CMakeFiles/Game.dir/Game/rtexture.cpp.o 

Każda pomoc? Dzięki.

+0

Używasz '#ifndef CLEANUP_H #define CLEANUP_H # endif' w cleanup.h? Jeśli nie, musisz go użyć. – Jahid

+0

Nie, używam go - przepraszam za spóźnioną odpowiedź. Jak w poniższych odpowiedziach, 'inline void' działa, ale dzięki to. –

Odpowiedz

10

Specyficzne specjalizacje szablonów funkcji podlegają regule jednej definicji, tak jak są to zwykłe funkcje. Dodaj inline, aby zezwolić na definicje w nagłówku; lub zdefiniuj je w pliku źródłowym, z deklaracjami w nagłówku.

5

Nie widzę żadnych strażników. Ponadto, ponieważ ten nagłówek jest zawarty w wielu plikach .cpp, #ifdef nie jest enugh - należy użyć słowa kluczowego inline, które mówi linkerowi, że dana funkcja może być zdefiniowana w więcej niż jednej jednostce tłumaczeniowej.

#ifndef CLEANUP_H 
#define CLEANUP_H 

//includes... 

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

#endif /* CLEANUP_H */ 
Powiązane problemy