应用C 11将语义移动到绑定函数
我有一些现有的C 98代码,它使用boost :: function和boost:bind进行异步回调.代码的一些相关简化片段包括:
typedef boost::function<void (boost::system::error_code,size_t)> WriteHandler; struct WriteOperation { WriteOperation(const boost::shared_ptr<IDevice>& device,const std::string& data,const WriteHandler& handler) : m_Device(device),m_Data(data),m_Handler(handler) {} private: boost::shared_ptr<IDevice> m_Device; std::string m_Data; WriteHandler m_Handler; void Complete() { boost::system::error_code ec; size_t len; ... Async::Post(boost::bind(m_Handler,ec,len)); } }; struct Device : public IDevice { void Write(const std::string& data,const WriteHandler& callback) { ... Async::Start(new WriteOperation(shared_from_this(),data,boost::bind(&Device::HandleWrite,this,handler,_1,_2))); } private: void HandleWrite(const WriteHandler& callback,boost::system::error_code ec,size_t len) { ... callback(ec,len); } }; 在构造WriteOperation时有一个必需的副本,但除此之外我试图避免副本,因为它们可能非常昂贵. 我在思考如何最好地写出C 11世界.显而易见的缺点是WriteOperation构造函数在内部将其参数复制到其字段中,因此应使用自动复制习惯用法: WriteOperation(boost::shared_ptr<IDevice> device,std::string data,WriteHandler handler) : m_Device(std::move(device)),m_Data(std::move(data)),m_Handler(std::move(handler)) {} (当然,裸新应该用unique_ptr替换,但这是一个副问题.) 但是,考虑到当前Device :: Write的实现,我认为这实际上并没有获得任何好处,因此也应该改变.我的问题是,我真的没有看到一个很好的方法来做到这一点.根据this advice,我有三个选择: >声明多个重载(一个使用const&和一个使用&&) – 但由于这有两个参数,这两个参数都可以从移动语义中受益,这将需要四次重载 – 对于具有更多参数的方法,指数会更糟.此外,这会导致代码重复或将代码分散到其他方法上,这会影响可读性. 我错过了什么吗?有更好的解决方案吗?或者这只是移动语义没有任何区别的情况? 相关案例: typedef boost::function<void (boost::system::error_code,const std::string&)> ReadHandler; void Read(const ReadHandler& callback) { ... boost::bind(&Device::HandleRead,callback,_2) ... } void HandleRead(const ReadHandler& callback,const std::string& data) { ... callback(ec,data); } 这一切看起来应该没问题,没有复制,也不需要移动语义.而且我不确定传递给Read的ReadHandler. 解决方法
按粗略顺序:
如果复制和移动一样昂贵,那么请使用const& ;. 如果您可靠地保留副本,并且移动便宜,则按价值计算. 如果做不到这一点,您可以将其填入标题中,并且可以使用sfinae或无约束模板,使用转发引用. 如果失败,如果参数数量有限,则写入每个重载.这是参数数量的2 ^ n,所以最好不要太多.在内部转发到基于转发参考的实现. 如果不这样做,你真的需要效率吗? 如果做不到这一点,请输入“T的创建者”. template<class T,using Base=std::function<T()>> struct creator_of: Base { template<class U,std::enable_if_t<std::is_constructible<T,U&&>{},int> =0 > creator_of(U&&u): Base([&]()->T{ return std::forward<U>(u); }) {} template<class U,std::result_of_t<std::decay_t<U>()>{},int> =0 > creator_of(U&&u): Base(std::forward<U>(u)) {} creator_of(creator_of&&)=default; creator_of(): Base([]()->T{return {};}} {} }; 根据需要增加. creator_of< std :: string>可以从可以构造std :: string的东西构建,也可以从返回std :: string的函数对象构造. 在内部你可以调用()一次. (代码未编译,但设计合理.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |