静态表生成与GCC一起使用但不是clang; 铿锵叫?

Cor*_*lks 5 c++ templates partial-specialization static-members language-lawyer

我曾经编写过一些代码,在编译时为一些模板元编程生成一个静态表/数组(想法是C样式的字符串可以在编译时构建(它们只是char数组)).这个想法和代码是基于David Lin回答:

#include <iostream>

const int ARRAY_SIZE = 5;

template <int N, int I=N-1>
class Table : public Table<N, I-1>
{
public:
    static const int dummy;
};

template <int N>
class Table<N, 0>
{
public:
    static const int dummy;
    static int array[N];
};

template <int N, int I>
const int Table<N, I>::dummy = Table<N, 0>::array[I] = I*I + 0*Table<N, I-1>::dummy;

template <int N>
int Table<N, 0>::array[N];

template class Table<ARRAY_SIZE>;

int main(int, char**)
{
    const int *compilerFilledArray = Table<ARRAY_SIZE>::array;
    for (int i=0; i < ARRAY_SIZE; ++i)
        std::cout<<compilerFilledArray[i]<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 4.9.2编译此代码的工作原理如下:

$ g++-4.9 -Wall -pedantic b.cpp
$ ./a.out
0
1
4
9
16
Run Code Online (Sandbox Code Playgroud)

然而,Clang 3.5抱怨:

$ clang++ -Wall -pedantic b.cpp
Undefined symbols for architecture x86_64:
  "Table<5, 0>::dummy", referenced from:
      ___cxx_global_var_init in b-b8a447.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

dummy并且array都给出了Table类之外的定义(它们被声明的地方).据我所知,这应该满足链接器的要求.

这是clang的错误吗?

Col*_*mbo 6

必须单独定义每个主要和部分专业化静态数据成员.

template <int N, int I>
const int Table<N, I>::dummy = …;
Run Code Online (Sandbox Code Playgroud)

这里定义的唯一内容是Table<N, I>::dummy- 主要特化静态数据成员.[temp.class.spec.mfunc]/1 1:

应定义以需要定义的方式使用的类模板部分特化成员; 主模板成员的定义从不用作类模板部分特化的成员的定义.

这也意味着GCC在这里是错误的.那是一个错误.
无论如何,添加

template <int N>
const int Table<N, 0>::dummy = 0;
Run Code Online (Sandbox Code Playgroud)

应编译好.


1) 特别是在与上面引用相同的部分中:

类模板部分特化的成员的模板参数列表应匹配类模板部分特化的模板参数列表.
类模板部分特化的成员的模板参数列表应匹配类模板部分特化的模板参数列表.

这意味着用于定义部分特化及其成员的参数列表必须相同.否则该成员永远不会被定义.