I'm having trouble finding why the following very small program doesn't compile:
#include <stdint.h>
// Returns the alpha value of a texel at position (x, y) from src.
static inline uint8_t get_alpha(const uint8_t *src, int rowBytes, int x, int y) {
return *(src + y*rowBytes + x);
}
typedef uint8_t (*GetAlphaProc)(const uint8_t* src, int rowBytes, int x, int y);
template<GetAlphaProc getAlphaProc>
static void compress_block(uint8_t** dst, const uint8_t* src, int rowBytes) {
// Do some trivial stuff
uint64_t out = 0x0000000001FE000173ULL;
uint8_t a = getAlphaProc(src, rowBytes, 0, 0);
*(reinterpret_cast<uint64_t*>(*dst)) = (static_cast<uint64_t>(a) << 32) | out;
}
int main() {
// Initialization
uint8_t src[144]; for (int i = 0; i < 144; ++i) src[i] = i;
uint64_t out;
uint64_t* dst = &out;
uint8_t** dstPtr = reinterpret_cast<uint8_t**>(&dst);
compress_block<get_alpha>(dstPtr, src, 12);
}
The errors that are being produced are:
[user ~/test]$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[user ~/test]$ g++ test-linkage.cpp -o testl
test-linkage.cpp: In function ‘int main()’:
test-linkage.cpp:25:46: error: ‘get_alpha’ is not a valid template argument for type ‘uint8_t (*)(const uint8_t*, int, int, int) {aka unsigned char (*)(const unsigned char*, int, int, int)}’ because function ‘uint8_t get_alpha(const uint8_t*, int, int, int)’ has not external linkage
test-linkage.cpp:25:46: error: no matching function for call to ‘compress_block(uint8_t**&, uint8_t [144], int)’
test-linkage.cpp:25:46: note: candidate is:
test-linkage.cpp:11:13: note: template<uint8_t (* getAlphaProc)(const uint8_t*, int, int, int)> void compress_block(uint8_t**, const uint8_t*, int)
The question is why the error has not external linkage matters for g++? All of the functions involved in this code have internal storage, and from most of the documentation that I was able to google, this is allowed for static functions. How come function template arguments must have external linkage when being compiled in a single module?
EDIT
Similar build problems under clang++:
[user ~/test]$ clang++ --version
Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
[user ~/test]$ clang++ -std=c++11 test-linkage.cpp -o testl
test-linkage.cpp:25:5: error: no matching function for call to 'compress_block'
compress_block<get_alpha>(dstPtr, src, 12);
^~~~~~~~~~~~~~~~~~~~~~~~~
test-linkage.cpp:11:13: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'getAlphaProc'
static void compress_block(uint8_t** dst, const uint8_t* src, int rowBytes) {
^
1 error generated.
g++ 4.6.3should be emphasized maybe. @mokosha Get a newer compiler.