以下のすべてのコンパイラ (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")
(参考資料があれば幸いです)? 上記のコンパイル時のアサーションが発生しないようにするには、何と比較すればよいでしょうか?
ベストアンサー1
[注: もともと、これは自分で答える質問ではありませんでした。調査の試みを説明しているときに、たまたま自分で答えを見つけたので、それを共有できたらいいと思ったのです。]
C++11 標準の Annex C (2.14.5) によると:
文字列リテラルの型が「charの配列」から「const char の配列」[....]
さらに、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&
、T
は の型である。e
;— それ以外の場合は
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
変数はhello
左辺値でもあるため、質問文の2番目のコンパイル時アサーションは実行されません。括弧なしの ID 式であり、これはパラグラフ 7.1.6.2/4 の上記リストの最初の項目に該当します。したがって、 の結果はdecltype(hello)
によって名前が付けられたエンティティの型でありhello
、 ですchar const[6]
。