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

Tim*_*ann 49 c++ c++11

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

class Dimension
{
public:

    constexpr Dimension() noexcept;

    constexpr Dimension(int w, int h) noexcept;

    int width;
    int height;

};
Run Code Online (Sandbox Code Playgroud)

我认为我可以像在所有类中一样将定义放在一个单独的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) {}
Run Code Online (Sandbox Code Playgroud)

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

警告:内联函数' 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;

};
Run Code Online (Sandbox Code Playgroud)

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

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

Tim*_*ann 48

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

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

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

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

[basic.def.odr]§3.2/ 4

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


Yit*_*ikC 10

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