C ++类是否可以在头文件中包含内联初始化的静态const std :: array?

时间:2015-10-18 22:37:28

标签: c++ c++11

这就是我所拥有的:

struct Foo
{
   static std::array<double, 4> acgt_default_background_frequencies() { return {0.281774, 0.222020, 0.228876, 0.267330}; }
};

但我更喜欢不使用函数而只是有一个变量,如下所示:

struct Foo
{
   static constexpr std::array<double, 4> acgt_default_background_frequencies = {0.281774, 0.222020, 0.228876, 0.267330};
};

我想要编译,但是当我try to use Foo::acgt_default_background_frequencies时,它会给链接器错误“未定义引用`Foo :: acgt_default_background_frequencies'”。

我想做的是什么?我认为我的标题的读者更清楚,如果我将值内联为const而不是将其隐藏在.cpp文件中并且具有常量而不是函数也看起来更清晰。 constexpr是不是允许这样的东西?如果不可能,为什么不呢?

1 个答案:

答案 0 :(得分:6)

第二个示例中的内容是constexpr std::array<double, 4> Foo::acgt_default_background_frequencies; 数据成员的声明,它有一个初始值设定项,但您没有在任何地方提供定义 。如果您使该成员odr-use,则需要定义。

要提供定义,请将以下内容添加到.cpp文件

struct Foo
{
  static constexpr std::array<double, AlphabetSize> acgt_default_background_frequencies = {{0.281774, 0.222020, 0.228876, 0.267330}};
};

问题中的声明适用于C ++ 14,但请注意,在C ++ 11中,您需要一组额外的花括号,例如。

static

N3337的相关标准§9.4.2/ 3 [class.static.data]

  

...文字类型的constexpr数据成员可以使用<select>说明符在类定义中声明;如果是这样,它的声明应指定一个大括号或等于初始化,其中作为赋值表达式的每个 initializer-clause 是一个不断表达。 ...如果程序中使用了odr-used(3.2),并且命名空间作用域定义不包含初始化程序,则该成员仍应在命名空间作用域中定义。