ここでどのような回避策が必要かわかりません。関数オブジェクトの呼び出し式とターゲット シグネチャを変更できないと仮定すると、右辺値参照をラップし、ラップされたオブジェクト (一時オブジェクト) を const ref 経由で渡すことができます。基本的に、呼び出しは次のように展開されます。f( wrap(move(o)) );
i = bind(&f);
バインドが機能しないため、完全な転送に問題があると思われます。したがって、呼び出しが次のように解決されるように、完全な転送を実行する中間ステップを導入しました。f( move( (Object&)wrap( move(o) ) ) );
#include <iostream>
#include <functional>
using namespace std;
struct Object { int m; };
// target function with fixed signature (assuming we cannot change that)
void f(Object&& p) { p.m = 42; std::cout << p.m; };
// was surprised I didn't find any method to chain functions in the StdLib
// so here's my own:
template < typename F1, typename F2, typename P1 >
auto chain2(F1 f1, F2 f2, P1&& p1)
-> decltype( f1(f2( std::forward<P1>(p1) )) )
{
return f1( f2( std::forward<P1>(p1) ) );
}
// a special bind version; mostly syntactic sugar
// note you can also deduce the first template parameter; would be more work
// and not necessary here
template < typename P1, typename F1, typename F2 >
auto bind_chain(F1 f1, F2 f2)
-> decltype( std::bind( &chain2<F1,F2,P1>, f1, f2, std::placeholders::_1 ) )
{
return std::bind( &chain2<F1,F2,P1>, f1, f2, std::placeholders::_1 );
}
// as `std::move` is overloaded, we make things a little bit simpler;
// we later will need to get a function pointer on this, that's why
// I'd like to avoid too much overloading
template < typename T >
// for a certain reason, cannot use && here --------v, clang++3.2 accepts it
typename std::remove_reference<T>::type && my_move(T& p)
{
return std::move(p);
}
struct wrapper
{
Object&& m;
wrapper(Object&& p) : m(std::move(p)) {}
operator Object&() const { return m; }
// alternatively:
// operator Object&&() const { return std::move(m); }
};
int main()
{
Object o;
// we'll need to call the functor with an const ref
function<void(wrapper const&)> i;
// chaining the conversion to rvalue ref with the target function
i = bind_chain<wrapper const&>( &f, &my_move<Object> );
i( move(o) );
return 0;
}