- utility[meta header]
- std[meta namespace]
- function template[meta id-type]
- cpp11[meta cpp]
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
}
- remove_reference[link /reference/type_traits/remove_reference.md]
関数テンプレートの引数を転送する。
この関数は、渡された引数を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)
投げない
- (2) : この形式が左辺値参照の型に対して呼ばれた場合、プログラムは不適格である。(例:
std::forward<int&>(1)
は不適格)
#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
}
- std::forward[color ff0000]
- C++11
- Clang: ??
- GCC:
- GCC, C++11 mode: 4.6.1
- ICC: ??
- Visual C++: 2010, 2012, 2013, 2015