web-dev-qa-db-ja.com

constexpr const char * vs constexpr const char []

「最初の試行」はコンパイルされませんが、2番目の試行はコンパイルされます。どうして?違いは何ですか?

最初の試み:

#include <iostream>

int main()
{
    constexpr const char text2[] = "hello";
    constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression
    std::cout << b << std::endl;
}

2回目の試行:

#include <iostream>
int main()
{
constexpr const char * text1 = "hello";
constexpr const char * a = &text1[4];
std::cout << a << std::endl;

return 0;
}

(g ++バージョン4.9.2)でコンパイルします

g++ -std=c++11 -o main *.cpp

次のエラーが発生します

main.cpp: In function 'int main()':
main.cpp:7:40: error: '& text2[4]' is not a constant expression constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression  
20

ドラフトC++ 11標準セクション5.19[expr.const]から、 アドレス定数式 is(強調鉱山ゴングフォワード):

[...] prvalueコア定数式静的ストレージ期間を持つオブジェクトのアドレスに評価されるポインター型、関数のアドレス、またはnullポインター値、またはprvalue std :: nullptr_t型のコア定数式。

最初のケースでは、"hello"は静的な保存期間を持つ文字列リテラルですが、静的ストレージ期間のない配列text2にコピーされます。

2番目のケースでは、text1は静的な保存期間を持つ 文字列リテラル へのポインタです。

最初の例を変更してtext2を静的(ライブで参照):

constexpr char static text2[] = "hello";
               ^^^^^^

エラーが発生しなくなりました。

セクション2.14.5[Lex.string]から、文字列リテラルに静的な保存期間があることがわかります。

通常の文字列リテラルおよびUTF-8文字列リテラルは、ナロー文字列リテラルとも呼ばれます。狭い文字列リテラルのタイプは「arrayofn const char」です。ここで、nは以下に定義する文字列のサイズであり、静的ストレージ期間(3.7)があります。

22
Shafik Yaghmour