1

の使用法に関するこの例std::forwardは、私を困惑させます。これは私の編集版です:

#include <iostream>
#include <memory>
#include <utility>
using namespace std;

struct A{
    A(int&& n) { cout << "rvalue overload, n=" << n << "\n"; }
    A(int& n)  { cout << "lvalue overload, n=" << n << "\n"; }
};

template<typename> void template_type_dumper();

template<class T, class U>
unique_ptr<T> make_unique(U&& u){
    //Have a "fingerprint" of what function is being called
    static int dummyvar;
    cout<<"address of make_unique::dummyvar: "<<&dummyvar<<endl;
    //g++ dumps two warnings here, which reveal what exact type is passed as template parameter
    template_type_dumper<decltype(u)>;
    template_type_dumper<U>;

    return unique_ptr<T>(new T(forward<U>(u)));
}

int main()
{
    unique_ptr<A> p1 = make_unique<A>(2); // rvalue
    int i = 1;
    unique_ptr<A> p2 = make_unique<A>(i); // lvalue
}

出力は

address of make_unique::dummyvar: 0x6021a4
rvalue overload, n=2
address of make_unique::dummyvar: 0x6021a8
lvalue overload, n=1

参照に関する警告template_type_dumperは、最初のインスタンス化ではそれを示し、2 番目のインスタンス化ではdecltype(u) = int&&とを示します。U = intdecltype(u) = int&U = int&

予想どおり 2 つの異なるインスタンス化があることは明らかですが、それは私の質問です。

  1. ここでどのようstd::forwardに働くことができますか?最初のインスタンス化では、そのテンプレート引数は明示的U = intに です。右辺値参照を返す必要があることをどのように知ることができますか? U&&代わりに指定するとどうなりますか?
  2. make_unique右辺値参照を取るように宣言されています。なぜ左辺値参照になることがuできますか? 私が見逃している特別なルールはありますか?
4

1 に答える 1

4

make_unique右辺値参照を取るように宣言されています。なぜあなたは左辺値参照になることができますか? 私が見逃している特別なルールはありますか?

make_unique参照を取るように宣言されています。その参照がどのようなものであるかを推測する必要があります。型の左辺値fooが渡された場合、参照の折りたたみ規則 (基本的に、左辺値参照を別の参照と「組み合わせる」と、常に左辺値参照が生成されます。2 つの右辺値参照を結合すると、右辺値参照が生成されます) により、次のUように推定されfoo&ます。型の右辺値が渡された場合、 isおよびisと推定されます。U&&foo&fooUfooU&&foo&&

これは、完全転送U&&を可能にするものの 1 つです。左辺値と右辺値の両方を使用できU、適切な値カテゴリに一致すると推測されます。次に、std::forward同じ値カテゴリを保持して値を転送できます。最初のケースではstd::forward<foo&>、左辺値を転送するものを取得し、2 番目のケースではstd::forward<foo>、右辺値を転送するものを取得します。

最初のインスタンス化では、そのテンプレート引数は明示的に U = int ですが、右辺値参照を返す必要があることをどのように知ることができますか?

の戻り値の型std::forward<T>は常にT&&. 渡すintと、 が返されますint&&。パスすると、参照の折りたたみルールにより、再びint&返されます。int&

代わりに U&& を指定するとどうなりますか?

あなたは持っているだろうstd::forward<int&&>し、参照折りたたみルールはint&& &&まだ右辺値参照を作る: int&&.

于 2012-04-30T20:26:20.627 に答える