模板静态constexpr定义odr使用的变量

时间:2016-04-08 18:52:58

标签: c++ templates c++11 gcc constexpr

实际代码更复杂,但我能够将其简化为此示例。

一切正常,直到我尝试将指针指向MyPackets_t :: types(在main()中取消对foo()的调用)

此时,为了使应用程序链接,类型需要定义。

我正在努力使用正确的定义语法。注释掉模板......应该做的伎俩。然而,它产生错误“'PacketCollection :: types'的模板参数与原始模板不匹配。”

尝试这样的事情 - 模板<> constexpr int PacketCollection :: types []; - 导致另一个链接器错误,好像在该行中使用变量而不是声明。

我尝试使用MyPackets_t而不是PacketCollection - 结果相同。

如果我进行非模板化数据包收集,那么所有内容都会按预期编译并运行。

我觉得我要么缺少一些非常基本的东西,要么编译器中存在错误。我用gcc 4.8和4.9得到了这个行为。

Clang 3.5对这种情况略有不同:constexpr静态数据成员'types'的声明需要一个初始化器。

到目前为止,我发现的唯一解决方法是使用

static constexpr std::array<int, 2> types() { return {1,2}; }

相反,但我不喜欢这个解决方案。如果变量在非模板化版本中工作(使用头文件中的初始化程序),它也适用于模板化版本。

#include <iostream>

using namespace std;

class Packet_A
{
public:
    static constexpr int TYPE = 1;
};

class Packet_B
{
public:
    static constexpr int TYPE = 2;
};

template <typename T> class PacketCollection
{
public:
    static constexpr size_t size = 2;
    static constexpr int types[size] { 1, 2 };
};

typedef PacketCollection<Packet_A> MyPackets_t;

//template<typename T> constexpr int PacketCollection<Packet_A>::types[PacketCollection<Packet_A>::size];

void foo(const int* bar, size_t size)
{
    if (size >= 2)
    {
        cout << bar[0] << bar[1];
    }
}

int main(int argc, char* argv[])
{
    cout << Packet_A::TYPE;
    cout << MyPackets_t::types[0];

    //foo(MyPackets_t::types, MyPackets_t::size);

    return 0;
}

1 个答案:

答案 0 :(得分:2)

您应该使用T代替Packet_A

template<typename T> constexpr int PacketCollection<T>::types[PacketCollection<T>::size];
                                                    ^                          ^

请参阅live example