次の構造体テンプレートを検討してください。
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 つのファクトリ関数が必要になります。