std::function 的显式右值模板参数
问题
在修改一个 仅可移动
的类 class Resources
相关调用接口遇到了些问题。
在移除了接口中不必要的移动语义参数的时候,发现修改后 std::function<Resources>
类型的 callback 编译出错了。
class Resources
和 callback 的简要声明如下:
class Resources final : boost::noncopyable {
public:
using output_callback_t = std::function<void(Resources)>;
explicit Resources(Resources&&) noexcept; // 移动构造
Resources(...); // 省略
private:
std::unique_ptr<Data> _resource;
};
看了下 GCC 中 std::function::operator ()
的实现:
/**
* @brief Invokes the function targeted by `*this`.
* @returns the result of the target.
* @throws `bad_function_call` when `!(bool)*this`
*
* The function call operator invokes the target function object
* stored by `this`.
*/
_Res
operator()(_ArgTypes... __args) const
{
if (_M_empty())
__throw_bad_function_call();
return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
}
std::function
在调用时使用 std::function
构造时的 _ArgTypes 作为 forward 模板参数,而非直接使用 operator() ()
的参数。
这导致 std::function::operator ()
在调用函数对象的时候丢失了 Resources 的右值性。
因此,此时形如如下的代码
auto foo() {
output_callback_t cb = [](Resources res) {};
Resources curr_res{};
cb(std::move(curr_res)); // 这里会编译出错~
}
正确做法
在声明仅可移动的对象作为参数的 std::function callback
的时候,需要显式将参数声明为右值引用,在此例中则为:
using output_callback_t = std::function<void(Resources&&)>
版权所有
版权归属:nmpassthf