1. ホーム
  2. c++

constexpr クラスをヘッダで宣言し、別の .cpp ファイルで定義することは可能ですか?

2023-08-09 11:37:17

質問

私は、クラス Dimension というクラスがあり、(他のクラスと同様に)Dimension.hというファイルで定義しています。

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を使っています。なぜ分離定義が機能しないのでしょうか?

どうすれば解決しますか?

もし constexpr 関数がヘッダ内部で定義されていない場合、コンパイラは constexpr 関数が定義されていないため、コンパイラーは他の全てのソースファイルをコンパイルしている間、 関数の定義を見ることができません。

明らかに、もし関数の定義を見ることができなければ、コンパイル時に関数を計算するために必要なステップを実行することができません。したがって、すべての constexpr 関数は、それらが使用されるすべての場所で定義されなければなりません。

ありがとう、@IgorTandetnik。

[dcl.constexpr] §7.1.5/2

constexpr の関数と constexpr コンストラクタは暗黙のうちにインライン化されます。

[基本.def.odr] §3.2/4

インライン関数は、それがodrで使用されるすべての翻訳単位で定義されなければならない。