2013-02-24 8 views
35

私はすべての私は、以下を試してみましたコンパイラ(GCC 4.7.2、GCC 4.8.0ベータ、ICC 13.0.1、クラン3.2、VC10)から予期しない結果を取得しています:decltype( "Hello")の結果は何ですか?

#include <type_traits> 

int main() 
{ 
    // This will fire 
    static_assert(
     std::is_same<decltype("Hello"), char const[6]>::value, 
     "Error!" 
     ); 
} 

私が持っているでしょうを上回るコンパイル時のアサーションが発生しないことが予想されますが、それは発生しませんが、は発生します。結局、この1つは(予想通り)ない:

#include <type_traits> 

int main() 
{ 
    char const hello[6] = "Hello"; 

    // This will not fire 
    static_assert(
     std::is_same<decltype(hello), char const[6]>::value, 
     "Error!" 
     ); 
} 

だからdecltype("Hello")の結果は、C++ 11標準(参照高く評価されている)に応じて何ですか?上記のコンパイル時のアサーションが発生しないように、私はそれをどのように比較すればよいですか?

答えて

29

[注:もともと、これは自己回答型の質問ではありませんでした。私は調査の試みを記述しているうちに答えを見つけたばかりだったので、それを分かち合うのがいいと思った。

文字列リテラルのタイプはCONSTチャーのアレイ」を「charの配列」から変更される:C++ 11の附属書C(2.14.5)によれば、標準]

「[...]

また、(decltypeの結果について)パラグラフ7.1.6.2/4指定:

次のようにdecltype(e)で示されるタイプが定義されている:

からeはunparenthesized ID-発現またはunparenthesizedクラスメンバアクセス(5.2.5)である場合、decltype(e)eによって指定されたエンティティのタイプです。そのようなエンティティが存在しない場合、またはeがオーバーロードされた関数のセットに名前を付ける場合、プログラムは不正です。

からeではxValueあればそうでない場合、decltype(e)Teのタイプであり、T&&あります。

- eが左辺値である場合にそうでなければ、decltype(e)Teのタイプであり、T&あります。

- それ以外の場合、decltype(e)eのタイプです。

#include <type_traits> 

int main() 
{ 
    // This will NOT fire 
    static_assert(
     std::is_same<decltype("Hello"), char const (&)[6]>::value, 
     "Error!" 
     ); 
} 

string literals are lvaluesので、上の段落および附属書Cのパラグラフによれば、decltype("Hello")の結果は一定の狭い文字のサイズ6のアレイに左辺値参照であります

最後に、hello変数は、値がであっても、質問のテキストからの2番目のコンパイル時アサーションhelloの括弧で囲まれていないid式であり、これはパラグラフ7.1.6.2/4の上記リストの最初の項目に該当するためです。したがって、decltype(hello)の結果はhelloという名前のエンティティのタイプであり、char const[6]です。

+0

これらのルールは、 'decltype(expr)&&'の記述を考えると意味があります。 –

+1

@KerrekSB:はい。私は「文字列リテラルには型const char []があります」、「decltype(x)」は 'x'の型を返すので、 hello ")'は 'const char [6]' "を返し、詳細を忘れてしまいます。レッスンは質問と回答の両方に –

+3

+1を学んだ(うまくいけば)。私はもうC++コンパイラには触れないことを約束します。 –

関連する問題