【问题标题】:template static constexpr definition of odr-used variableodr-used 变量的模板静态 constexpr 定义
【发布时间】:2016-07-30 03:56:15
【问题描述】:

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

一切正常,直到我尝试获取指向 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;
}

【问题讨论】:

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


    【解决方案1】:

    您应该使用T 而不是Packet_A

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

    live example

    【讨论】:

    • 谢谢!这已经奏效了。是否有规范部分解释其工作原理和方式?
    • @Ghostrider 参见例如[temp.static]/1 来自draft Standard:template&lt;class T&gt; class X { static T s; }; template&lt;class T&gt; T X&lt;T&gt;::s = 0;
    猜你喜欢
    • 1970-01-01
    • 2014-11-29
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2020-10-08
    相关资源
    最近更新 更多