是否可以在标头中声明constexpr类并在单独的.cpp文件中定义它?

时间:2014-12-07 17:09:46

标签: c++ c++11

我在文件Dimension.h中定义了一个类Dimension(就像我的所有类一样):

class Dimension
{
public:

    constexpr Dimension() noexcept;

    constexpr Dimension(int w, int h) noexcept;

    int width;
    int height;

};

我认为我可以像在所有课程中一样,将定义放在一个单独的Dimension.cpp中:

#include "Dimension.h"

constexpr Dimension::Dimension() noexcept : width(0), height(0) {}

constexpr Dimension::Dimension(int w, int h) noexcept : width(w), height(h) {}

但是当我尝试使用该类时,编译器会告诉我:

警告:内联函数“constexpr Dimension::Dimension()”已使用但未定义

和链接时:

对“pong::graphics::Dimension::Dimension()

的未定义引用

(与其他构造函数相同)

如果我在标题中定义类,那么:

class Dimension
{
public:

    constexpr Dimension() noexcept : width(0), height(0) {}

    constexpr Dimension(int w, int h) noexcept : width(w), height(h) {}

    int width;
    int height;

};

并省略.cpp文件,一切正常。

我正在使用GCC 4.9.2。为什么单独的定义不起作用?

2 个答案:

答案 0 :(得分:41)

如果标头内未定义constexpr函数,编译器在编译所有其他源文件时无法看到constexpr函数的定义。

显然,如果它看不到函数的定义,它就无法在编译时执行计算它们所需的步骤。因此,必须在使用它们的任何地方定义所有constexpr函数。

谢谢@IgorTandetnik:
[dcl.constexpr]§7.1.5/ 2

  

constexpr函数和constexpr构造函数是隐式内联的。

[basic.def.odr]§3.2/ 4

  

内联函数应在每个使用它的翻译单元中定义。

答案 1 :(得分:8)

您所要求的内容可以完成,但有一个显着的限制: constexpr 功能只能从定义它的翻译单元(即源文件)内部调用。这不适用于您给出的示例,因为构造函数应该是类的一部分。公共界面。然而,它在其他情况下非常有用,例如将私有方法定义为 constexpr ,然后在需要在编译时知道的表达式中使用它们的返回值,例如:模板实例化,切换语句标签等