【问题标题】:Static table generation works with GCC but not clang; is clang bugged?静态表生成适用于 GCC,但不适用于 clang; clang 被窃听了吗?
【发布时间】:2014-12-05 17:00:25
【问题描述】:

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

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

使用 GCC 4.9.2 编译此代码有效:

$ g++-4.9 -Wall -pedantic b.cpp
$ ./a.out
0
1
4
9
16

不过,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)

dummyarray 都是在 Table 类(它们被声明的地方)之外给出的定义。据我所知,这应该满足链接器的要求。

这是 clang 的错误吗?

【问题讨论】:

    标签: c++ templates language-lawyer static-members partial-specialization


    【解决方案1】:

    每个主要和部分特化静态数据成员都必须单独定义。

    template <int N, int I>
    const int Table<N, I>::dummy = …;
    

    这里唯一定义的是Table&lt;N, I&gt;::dummy - 主要特化静态数据成员。 [temp.class.spec.mfunc]/11:

    以某种方式使用的类模板偏特化成员 需要定义的,应予以定义; 的定义 主模板的成员永远不会用作定义 类模板部分特化的成员。

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

    template <int N>
    const int Table<N, 0>::dummy = 0;
    

    应该可以正常编译。


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

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

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

    【讨论】:

    • 啊,有道理!可惜我只能投票一次。另外,我期待您收到标准报价。
    • @Cornstalks 他们在那里 :)
    • 能否请您添加指向 gcc 错误报告的链接?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    • 1970-01-01
    • 2014-11-26
    • 2014-12-21
    • 1970-01-01
    • 2022-12-08
    • 1970-01-01
    相关资源
    最近更新 更多