0

次の構造体テンプレートを検討してください。

template<typename T>
struct X
{
    X(T t) : t(std::forward<T>(t)) {}

    T t;
};

ここで、T は左辺値参照 (例: const int&) または通常の値 (例: )のいずれかになりますint。アイデアは、 lvalueXから構築されるときは常に lvalue-reference を使用し、 rvalueから構築されるときは通常の値を使用することです。

したがって、次のファクトリ関数は、そのXようなプロパティを持つのインスタンスを作成するために定義されています。

template<typename T>
X<const T&>
CreateX(const T& val)
{
    return X<const T&>(val);
}

template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, X<T>>::type
CreateX(T&& val)
{
    return X<T>(std::move(val));
}

ここまでは順調ですね。構造体テンプレートを考えるとY:

template<typename T, typename U>
struct Y
{
    Y(T t, U u) : t(std::forward<T>(t)), u(std::forward<T>(u)) {}

    T t;
    U u;
};

そして、 について前と同じ類推を行うことに決め、X最終的には次の 4 つのファクトリ関数になります。

template<typename T, typename U>
Y<const T&, const U&>
CreateY(const T& t, const U& u)
{
    return Y<const T&, const T&>(t, u);
}

template<typename T, typename U>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, Y<T, const U&>>::type
CreateY(T&& t, const U& u)
{
    return Y<T, const U&>(std::forward<T>(t), u);
}

template<typename T, typename U>
typename std::enable_if<std::is_rvalue_reference<U&&>::value, Y<const T&, U>>::type
CreateY(const T& t, U&& u)
{
    return Y<const T&, U>(t, std::forward<T>(u));
}

template<typename T, typename U>
typename std::enable_if<std::is_rvalue_reference<T&&>::value and std::is_rvalue_reference<U&&>::value, Y<T, U>>::type
CreateY(T&& t, U&& u)
{
    return Y<T, U>(std::forward<T>(t), std::forward<T>(u));
}

同じ結果を得る別の方法はありますか?おそらく冗長ではありませんか? 幸いなことに、私のアプリケーションは 2 つ以上のテンプレート データ メンバーを必要としませんが、その他のいくつかのクラスYが必要になり、それぞれに 4 つのファクトリ関数が必要になります。

4

1 に答える 1

4

これにより、左辺値から構築されたときに非定数左辺値参照が発生し、それらを const 左辺値参照にしたいと思います

左辺値参照を変換する単純なトレイトを書くことができます:

template<class T>
struct transform_parameter{ using type = T; };

template<class T>
struct transform_parameter<T&>{ using type = T const&; };

template<class T>
using TransformParameter = typename transform_parameter<T>::type;

そして、それを関連するすべてのテンプレート パラメータに適用します。

template<class T>
X<TransformParameter<T>> make_X(T&& v){
  return {std::forward<T>(v)};
}

また、ここではブレース初期化リスト (別名、一様な初期化) を使用して、型を 2 回記述しないようにしました。

于 2013-08-08T13:36:05.110 に答える