【问题标题】:Undefined symbols for architecture x86_64 linking constexpr std::array架构 x86_64 链接 constexpr std::array 的未定义符号
【发布时间】:2017-06-07 00:08:18
【问题描述】:

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

#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。

【问题讨论】:

  • 你是否包含标题
  • 是的,当然。
  • 这个表达式有错别字Sytem::objet_per_socket.begin(),应该是System而不是Sytem
  • 您的问题几乎肯定是您没有发布的问题。请发布一个完整的(并且最少 - 足以触发错误的代码)示例:即所有相关文件,以及您执行的实际命令行和您得到的错误的实际文本。
  • @aaaramoon 问题是你必须在类定义之外定义std::array类型的静态数据成员。

标签: c++ c++14 constexpr


【解决方案1】:

在 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 标志的代码。

【讨论】:

  • 感谢您的回复,我不太清楚一件事,我应该将初始化移动到另一个文件中,还是应该在其他地方声明变量?
  • @aaaramoon 将我的答案中的行复制并粘贴到 .cpp 文件中,不要更改您的类定义
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多