静态函数模板参数的外部链接

时间:2014-07-28 18:06:59

标签: c++ templates g++

我无法找到以下非常小的程序无法编译的原因:

#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);
}

正在产生的错误是:

[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)

问题是为什么错误has not external linkage对g ++很重要?此代码中涉及的所有功能都具有内部存储,并且从我能够谷歌的大多数文档中,这是允许静态功能。为什么函数模板参数在单个模块中编译时必须具有外部链接?

修改

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.

2 个答案:

答案 0 :(得分:3)

它只是一个硬规则,没有例外,模板参数不能有内部链接。这是一个很难的规则,因为没有足够的实施经验可以告诉我们在哪里可以获得这样的模板参数。

在C ++ 11中,改变了,因为我们现在知道编译器可以在没有太多问题的情况下处理它。模板参数现在可以具有内部链接。要在C ++ 11模式下进行编译,请将-std=c++11传递给命令行参数,或-std=gnu++11以启用更多扩展。

请注意,millsj的回答正确地指出了代码中的不同问题,修复您要求的问题也会让GCC报告。

答案 1 :(得分:1)

compressed_block期待uint8_t**作为其第一个参数,但您要给它uint64_t*

static void compress_block(uint64_t* dst, const uint8_t* src, int rowBytes)

这在VS2013上编译并运行。