10

次のテストプログラムがあります。

#include <iostream>
#include <type_traits>
#include <utility>

template<typename Ty, std::size_t N>
void foo(Ty (&&)[N])
{
    std::cout << "Ty (&&)[" << N << "]\t" << std::is_const<Ty>::value << '\n';
}

template<typename Ty, std::size_t N>
void foo(Ty (&)[N])
{
    std::cout << "Ty (&)[" << N << "]\t" << std::is_const<Ty>::value << '\n';
}

template<typename Ty>
using id = Ty;

int main()
{
    std::cout.setf(std::cout.boolalpha);

    foo(id<int[]>{1, 2, 3, 4, 5});
    foo(id<int const[]>{1, 2, 3, 4, 5}); // <-- HERE.
    int xs[]{1, 2, 3, 4, 5};
    foo(xs);
    int const ys[]{1, 2, 3, 4, 5};
    foo(ys);
    foo(std::move(xs));
    foo(std::move(ys));
}

矢印でマークされた行は、そのすぐ上の非 const 呼び出しのように右辺値オーバーロードを呼び出すと予想されますが、そうではありません。

これは GCC の単なるバグですか、それとも左辺値のオーバーロードが選択される原因となる標準の何かがありますか?

4

1 に答える 1

2

標準によると§12.2 [class.temporary]

クラス型のテンポラリは、prvalue への参照のバインド (8.5.3)、prvalue を返す (6.6.3)、prvalue を作成する変換 (4.1、5.2.9、5.2.11、5.4) など、さまざまなコンテキストで作成されます。 、例外のスロー (15.1)、ハンドラーの開始 (15.3)、および一部の初期化 (8.5)。

id<int const[]>{1, 2, 3, 4, 5}一時的であるため、 prvalueです§3.10 [basic.lval]

右辺値 (右辺値は代入式の右側に現れる可能性があるため、歴史的にそう呼ばれています) は、xvalue、一時オブジェクト (12.2) またはそのサブオブジェクト、またはオブジェクトに関連付けられていない値です。

prvalue (「純粋な」右辺値) は、xvalue ではない右辺値です。

したがって、右辺値参照引数を持つオーバーロードされた関数を選択する必要があります。

于 2013-07-14T08:15:52.620 に答える