36

以下を試したすべてのコンパイラ(GCC 4.7.2、GCC 4.8.0ベータ、ICC 13.0.1、Clang 3.2、VC10)から予期しない結果が得られます。

#include <type_traits>

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

上記のコンパイル時のアサーションが起動しないことを期待していましたが、起動します。結局のところ、これは(予想どおり)ではありません:

#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!"
        );
}

では、C ++ 11標準に準拠した結果はどうなるdecltype("Hello")でしょうか(参照は高く評価されています)。上記のコンパイル時のアサーションが起動しないようにするには、何と比較する必要がありますか?

4

1 に答える 1

30

[注:元々、これは自己回答の質問を意図したものではありませんでした。調査の試みを説明しているときに、たまたま自分で答えを見つけたので、それを共有できればよかったと思いました。]

C ++ 11規格の付録C(2.14.5)によると:

文字列リテラルの型が「arrayofchar」から「<strong>arrayofconstchar」に変更されました。[....]

さらに、7.1.6.2 / 4項では、(の結果についてdecltype)次のように規定しています。

で示されるタイプdecltype(e)は次のように定義されます。

eが括弧で囲まれていないid式または括弧で囲まれていないクラスメンバーアクセス(5.2.5)の場合、はでdecltype(e)指定されたエンティティのタイプですe。そのようなエンティティがない場合、またはeオーバーロードされた関数のセットに名前を付ける場合、プログラムの形式は正しくありません。

—それ以外の場合、eがxvalueの場合、decltype(e)T&&、です。ここで、は;Tのタイプです。e

それ以外の場合、eが左辺値の場合、decltype(e)T&、です。ここTeで、は;のタイプです。

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

文字列リテラルは左辺値であるため、上記の段落および付録Cの段落によると、結果decltype("Hello")は、定数の狭い文字のサイズ6の配列への左辺値参照になります。

#include <type_traits>

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

最後に、hello変数左辺値ですが、質問のテキストからの2番目のコンパイル時アサーションは起動しません。これは、括弧で囲まれていないid式helloであるため、 7.1.6.2項の上記のリストの最初の項目に分類されます。 /4。したがって、の結果は、で指定されたエンティティのタイプであり、です。decltype(hello)hellochar const[6]

于 2013-02-24T00:17:48.703 に答える