web-dev-qa-db-ja.com

ヘッダーファイルでのconstexprの使用

ヘッダーファイルにこのような定義を含めることができますか?

 constexpr double PI=3.14;

これをいくつかのcppファイルに含まれるヘッダーファイルに含めることに問題はありますか?

標準では、このconstexprには独自のメモリがあり、ヘッダーに追加し、いくつかのcppファイルにヘッダーを追加すると標準で述べているので、メモリ内の同じ値の複数のコピーとその他の厄介な問題を生成するのではないかと心配しています。

私はC++ 11を使用しています

20
mans

constexprconstを意味し、グローバル/ネームスペーススコープのconststatic(内部リンケージ)を意味します。つまり、このヘッダーを含むすべての翻訳単位はPI。その静的のメモリは、アドレスまたはそれへの参照が取得され、アドレスが各変換単位で異なる場合にのみ割り当てられます。

static変数のconst変数は、C++のヘッダーファイルで#defineの代わりにconstを使用して定数を定義するために導入されました。 staticがなければ、リンクされた複数の翻訳単位にヘッダーファイルが含まれている場合、複数のシンボル定義リンカーエラーが発生します。

C++ 17では、inlineにすることもできます。そのため、アドレスまたは参照が取得された場合(つまり、PIではない)staticのコピーは1つだけです。 inline変数はC++ 17で導入され、ヘッダーファイルに非const変数定義を持つヘッダーのみのライブラリを許可します。静的データメンバーのconstexprinlineを意味するため、inlineは不要です。

つまり、可能であれば、ヘッダーファイルの定数にconstexprを使用する必要があり、そうでない場合はconstを使用する必要があります。また、その定数のアドレスをどこでも同じにする必要がある場合は、inlineとしてマークします。

35

C++17あなたは明確です。 C++11、それを関数でラップすることができます:

constexpr double PI () { return 3.14; }
6
KevinZ

C++ 17 inline変数実行可能例

C++ 17インライン変数は、次の場所で言及されました: ヘッダーファイルでのconstexprの使用 これは、単一のメモリロケーションのみが使用されることを示す最小限の実行可能な例です。

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_i == notmain_func());
    assert(notmain_i == 42);
}

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline constexpr int notmain_i = 42;

const int* notmain_func();

#endif

notmain.cpp

#include "notmain.hpp"

const int* notmain_func() {
    return &notmain_i;
}

コンパイルして実行します:

g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main

GitHubアップストリーム

C++標準は、アドレスが同じであることを保証します。 C++ 17 N4659標準ドラフト 10.1.6 "インライン指定子":

6外部リンケージを持つインライン関数または変数は、すべての変換単位で同じアドレスを持たなければなりません。

cppreference https://en.cppreference.com/w/cpp/language/inline は、staticが指定されていない場合、外部リンケージがあることを説明します。

参照: constexpr externの宣言方法

GCC 7.4.0、Ubuntu 18.04でテスト済み。

C++ 20 std::math::pi

Piの特定のケースでは、C++ 20は次のように専用の変数テンプレートを提供します。 C++でPI定数を使用する方法