2017-09-08 9 views
12

は、我々は次のことを含むヘッダfoo.hを持って想像:C++標準:名前空間スコープのconstexpr変数に内部リンケージがありますか?

#ifndef FOO_H_ 
#define FOO_H_ 

namespace foo { 
constexpr std::string_view kSomeString = "blah"; 
} 

#endif // FOO_H_ 

foo.hを含む任意の翻訳単位で内部リンケージを持つことが保証foo::kSomeStringですか?これはC++ 11とC++ 17の間で異なりますか?ドラフトで

標準[basic.link]/3は、不揮発性const修飾型の非インライン可変[...]それの名前である場合、名前空間の範囲を有する名前が内部結合を有する

言いますどちらも明示的にextern宣言もなく、以前に外部リンケージを持つように宣言[...]

しかし、私は知っていない場合は、「const修飾」としてconstexprカウント。スタンダードはそうだと言いますか?

これは内部リンケージが保証されていると仮定すると、この使用法でODRに問題はないようですね。 (this answerとは対照的に)

+0

はい、 'constexpr'宣言はC++ 11では' const'を意味します。 C++ 14以降では、メンバ関数ではなく変数に 'const'を含めるだけです。 –

+0

ありがとう!スタンダードのどのセクションにそのことが分かっていますか? – jacobsa

答えて

13

はい、オブジェクト宣言のconstexprは、オブジェクトがconstであることを意味します。 [dcl.constexpr]/9を参照してください。はい、つまり、あなたの例のkSomeStringに内部リンケージがあることを意味します。

私たちがここで話しているODR違反の種は、kSomeStringの定義ではなく、それを使用しようとする他の定義です。そして内部結合のために正確に問題があります。検討:

void f(const std::string_view &); 

inline void g() { 
    f(foo::kSomeString); 
} 

複数の翻訳単位に含まれる場合、これはODR違反で、各翻訳単位でgの定義が異なるオブジェクトを参照し、基本的にするからです。

+0

ありがとうございます!あなたのODRの問題の例は理にかなっています。「g」は各翻訳単位で同じではありません。インライン関数に関係しない問題がある可能性はありますか? – jacobsa

関連する問題