5

次のようなクラス Box があるとします。

struct Base {}

template<typename T>
struct Box : Base
{
    template<typename... Args>
    Box(Args&&... args)
        : t(forward<Args>(args)...)
    {}

    T t;
}

そして、関数 MakeBox があります。

template<typename X>
Base* MakeBox(X&& x)
{
    return new Box<???>(forward<X>(x));
}

タイプXは、MakeBox の呼び出しで使用されるパラメーターから推測されます。

次に、X から適切な「ストレージ タイプ」パラメータ T を何らかの方法で計算する必要があります。

素朴に使用すると思います:

    return new Box<X>(forward<X>(x));

これは問題を引き起こします。

明らかstd::bindに、std::functionこれらの問題に対処する必要があります。

std::decayとにかくここで役に立ちますか?

4

2 に答える 2

3

あなたが達成したいことを正しく理解していれば、 を使用する必要がありますstd::decay。型のオブジェクトを に提供すると仮定するとSMakeBox()ユニバーサル参照X&&は、関数の引数を型にするか、引数が (それぞれ) 左辺値か右辺値かによってS&解決されます。S&&

これを実現するため、およびユニバーサル参照の C++11 規則により、最初のケースでは、テンプレート引数は次のように推定されます (メンバー変数はオブジェクトではなくオブジェクトである必要があるため、X=S&ここでXは への引数としては OK ではありません)。Box<>参照)、2 番目のケースではX=S(ここでXは への引数としては問題ありませんBox<>) と推定されます。適用することにより、へのテンプレート引数として提供する前に推定された型にstd::decayも暗黙的に適用れます。または_std::remove_referenceXBox<>XSS&XS&&SS&)。

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

using namespace std;

struct Base {};

template<typename T>
struct Box : Base
{
    template<typename... Args>
    Box(Args&&... args)
        : t(forward<Args>(args)...)
    {
    }

    T t;
};

template<typename X>
Base* MakeBox(X&& x)
{
    return new Box<typename decay<X>::type>(forward<X>(x));
}

struct S
{
    S() { cout << "Default constructor" << endl; }
    S(S const& s) { cout << "Copy constructor" << endl; }
    S(S&& s) { cout << "Move constructor" << endl; }
    ~S() { cout << "Destructor" << endl; }
};

S foo()
{
    S s;
    return s;
}

int main()
{
    S s;

    // Invoking with lvalue, will deduce X=S&, argument will be of type S&
    MakeBox(s);

    // Invoking with rvalue, will deduce X=S, argument will be of type S&&
    MakeBox(foo());

    return 0;
}

興味がある場合は、Scott Meyers による非常に優れたレッスンがあり、ユニバーサル参照がどのように動作するかを説明しています。

普遍的な参照に関するスコット・マイヤーズ

PS:この回答は編集されました:私の最初の回答は を使用することを提案しましたが、より良い選択であることstd::remove_reference<>std::decay判明しました。それを指摘した質問投稿者@Andrew Tomazos FathomlingCorpsと、元の質問へのコメントで最初に提案した@Mankarseの功績。

于 2012-12-30T22:18:52.870 に答える
1

提供された例(1)では、必要なことを行い、値を保存します。他のケース (xが配列の場合など) ではstd::decay、それをポインタに減衰させて格納するために使用できます。

于 2012-12-30T08:02:02.033 に答える