namespace std {
template <class T>
T&& forward(typename remove_reference<T>::type& t) noexcept; // (1) C++11
template <class T>
constexpr T&& forward(typename remove_reference<T>::type& t) noexcept; // (1) C++14
template <class T>
T&& forward(typename remove_reference<T>::type&& t) noexcept; // (2) C++11
template <class T>
constexpr T&& forward(typename remove_reference<T>::type&& t) noexcept; // (2) C++14
}
概要
関数テンプレートの引数を転送する。
この関数は、渡された引数をT&&
型にキャストして返す。(注:T
が左辺値参照の場合にはT&&
も左辺値参照になり、それ以外の場合にT&&
は右辺値参照になる。)
この関数は、主に転送関数(forwarding function)の実装を単純化する目的で使われる:
template <class... Args>
void forward_to_f(Args&&... args)
{
f(std::forward<Args>(args)...);
}
auto forward_to_f = [](auto&&... args)
{
f(std::forward<decltype(args)>(args)...);
};
この関数に渡した引数は、多くのケースにおいて右辺値参照にキャストされ、ムーブされることに注意すること。同じ引数に対して二回以上関数を呼び出しを行いたい場合は、std::forward()
は使ってはならない:
template <class T>
void bad(T&& x)
{
f(std::forward<T>(x)); // xはここでムーブされるかもしれないので
g(std::forward<T>(x)); // この関数呼び出しは予想外の結果になる可能性がある
}
template <class T>
void good(T&& x)
{
f(x); // まだ使う場合は転送は行わず、
g(std::forward<T>(x)); // 最後に使うときのみ転送すれば安全
}
戻り値
static_cast<T&&>(t)
例外
投げない
備考
例
#include <memory>
#include <utility>
template <class T, class A1, class A2>
std::shared_ptr<T> factory(A1&& a1, A2&& a2) {
return std::shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));
}
struct A {
A(int&, const double&) {}
};
int main()
{
//std::shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int&
int i = 2;
std::shared_ptr<A> sp2 = factory<A>(i, 1.414); // OK
}
xxxxxxxxxx
#include <memory>
#include <utility>
template <class T, class A1, class A2>
std::shared_ptr<T> factory(A1&& a1, A2&& a2) {
return std::shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));
}
struct A {
A(int&, const double&) {}
};
int main()
{
//std::shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int&
int i = 2;
std::shared_ptr<A> sp2 = factory<A>(i, 1.414); // OK
}
出力
バージョン
言語
- C++11
処理系
- Clang: ??
- GCC: 4.6.1 ✅
- ICC: ??
- Visual C++: 2010 ✅, 2012 ✅, 2013 ✅, 2015 ✅