I have this function header:
template <
bool src_alpha,
int sbpp, int dbpp,
typename T1, typename T2,
Color (*getFunc)(T1 data, Uint8* addr),
void (*putFunc)(T2 data, Uint8* addr, Color c)
>
static void OperateOnSurfaces(T1 data1, T2 data2, SDL_Surface * bmpDest, SDL_Surface * bmpSrc, SDL_Rect& rDest, SDL_Rect& rSrc)
This is how I use it:
OperateOnSurfaces<
true,
32, 32,
SDL_PixelFormat*, SDL_PixelFormat*,
GetPixel<true,32>, PutPixel<true,true,32> >(
bmpSrc->format, bmpDest->format,
bmpDest, bmpSrc, rDest, rSrc);
This is GetPixel
and PutPixel
:
template<bool alpha, int bpp>
static Color GetPixel(SDL_PixelFormat* format, Uint8* addr) { /* .. */ }
template<bool alpha, bool alphablend, int bpp>
static void PutPixel(SDL_PixelFormat* format, Uint8* addr, Color col) { /* .. */ }
And I get this error:
note: candidate template ignored: invalid explicitly-specified argument for template parameter 'getFunc' [3]
Why?
I suspect that all those functions are free functions. When you declare a free function static
, it gains internal linkage. Non-type template parameters, in C++03, must have external linkage†. Just remove static
in front of the functions.
template <
bool src_alpha,
int sbpp, int dbpp,
typename T1, typename T2,
char (*getFunc)(T1 data, unsigned* addr),
void (*putFunc)(T2 data, unsigned* addr, char c)
>
void OperateOnSurfaces(){}
template<bool alpha, int bpp>
char GetPixel(void* format, unsigned* addr);
template<bool alpha, bool alphablend, int bpp>
void PutPixel(void* format, unsigned* addr, char col);
int main(){
OperateOnSurfaces<
true,
32, 32,
void*, void*,
GetPixel<true,32>, PutPixel<true,true,32> >();
}
This modified example compiles fine on Clang 3.1 and GCc 4.4.5 in C++98 and C++11 mode, no warnings. If I leave the static
in, I get a similar error + note to what you got with Clang, and GCC spits out the vital information (scroll to the right, "has not external linkage"):
15:02:38 $ g++ t.cpp
t.cpp: In function ‘int main()’:
t.cpp:21: error: ‘GetPixel<true, 32>’ is not a valid template argument for type ‘char (*)(void*, unsigned int*)’ because function ‘char GetPixel(void*, unsigned int*) [with bool alpha = true, int bpp = 32]’ has not external linkage
t.cpp:21: error: ‘PutPixel<true, true, 32>’ is not a valid template argument for type ‘void (*)(void*, unsigned int*, char)’ because function ‘void PutPixel(void*, unsigned int*, char) [with bool alpha = true, bool alphablend = true, int bpp = 32]’ has not external linkage
t.cpp:21: error: no matching function for call to ‘OperateOnSurfaces()’
† (C++03) §14.3.2 [temp.arg.nontype] p1
A template-argument for a non-type, non-template template-parameter shall be one of:
[...]
the address of an object or function with external linkage [...]
[...]
Note that C++11 changed the wording and allows functions with internal linkage too now:
(C++11) §14.3.2 [temp.arg.nontype] p1
A template-argument for a non-type, non-template template-parameter shall be one of:
[...]
a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage [...]
[...]
Clang does currently not obey to this in C++11 mode, it still only allows functions with external linkage.