用于连接constexpr std :: array的体系结构x86_64的未定义符号

时间:2017-06-07 00:08:18

标签: c++ c++14 constexpr

我在链接目标文件时遇到错误:

#include <cstdint>
#include <array>

enum SystemType : uint8_t { AC, DC, HCP, EFF };

template<SystemType TYPE> struct System;

template<> 
struct System<AC> { 
public:     
static constexpr size_t number_of_sockets = 2;  
static constexpr std::array<size_t, number_of_sockets> object_per_socket { { 12, 6 } }; 
};

我正在使用它如下所示将数据分配到矢量中。

terminal->no_obj_per_system.assign(
            Sytem<AC>::object_per_socket.begin(),
            Sytem<AC>::object_per_socket.end());

我在mac Os上使用clang。

1 个答案:

答案 0 :(得分:5)

在C ++ 14及更早版本中,如果静态数据成员 odr-used ,则必须在一个翻译单元中具有类外定义;此规则仍适用于constexpr成员。

This question包含一个带有C ++ 14标准参考的示例。

如果没有提供类外定义,并且该变量是 odr-used ,那么它是错误的,不需要诊断,这解释了为什么有些人没有得到编译错误。为了安全起见,你应该提供一个定义,即使在变量不是 odr-used 的情况下,这样做也没有坏处。

定义看起来像(不在头文件中):

constexpr std::array<size_t, System<AC>::number_of_sockets>  System<AC>::object_per_socket;

在C ++ 17中有一个新功能“内联变量”,它允许在头文件中定义变量,其内联函数具有相似的语义,即允许跨翻译单元具有多个匹配定义,并且编译器/链接器将根据需要选择一个。 constexpr变量将隐式inline,因此您的原始代码在C ++ 17中是正确的。最新版本的gcc和clang应该接受带有-std=c++1z标志的代码。