C 11/14 INVOKE解决方法
发布时间:2020-12-16 07:16:53 所属栏目:百科 来源:网络整理
导读:我需要在某些C 11/14代码中使用INVOKE语义(由C 17中的std :: invoke实现).我当然不想自己实施,我认为这将是一场灾难.所以我决定利用现有的标准库设施.很快就想到了: templatetypename Fn,typename... Argsconstexpr decltype(auto) my_invoke(Fn f,Args...
我需要在某些C 11/14代码中使用INVOKE语义(由C 17中的std :: invoke实现).我当然不想自己实施,我认为这将是一场灾难.所以我决定利用现有的标准库设施.很快就想到了:
template<typename Fn,typename... Args> constexpr decltype(auto) my_invoke(Fn&& f,Args&&... args) noexcept(noexcept(std::bind(std::forward<Fn>(f),std::forward<Args>(args)...)())) { return std::bind(std::forward<Fn>(f),std::forward<Args>(args)...)(); } 这种实现的一个问题是它无法区分左值和右值(例如,如果函数对象在operator()()&和operator()()&&上重载,只有&&版本永远被称为).是否有一些库实用程序也完美转发可调用程序本身?如果没有,那么实施它的好方法是什么? (例如转发包装器). 解决方法
INVOKE的所有特殊案例都是关于成员的指针.只需SFINAE并将它们发送到mem_fn.
template<typename Fn,typename... Args,std::enable_if_t<std::is_member_pointer<std::decay_t<Fn>>{},int> = 0 > constexpr decltype(auto) my_invoke(Fn&& f,Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...))) { return std::mem_fn(f)(std::forward<Args>(args)...); } template<typename Fn,std::enable_if_t<!std::is_member_pointer<std::decay_t<Fn>>{},int> = 0> constexpr decltype(auto) my_invoke(Fn&& f,Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...))) { return std::forward<Fn>(f)(std::forward<Args>(args)...); } 这基本上是N4169中提出的最小实现.(真正的标准库实现者不这样做,因为将INVOKE功能集中在一个地方并且让各种其他部分调用它可以更加可维护.) 顺便说一下,使用std :: bind是完全错误的.它复制/移动所有参数,将它们作为lvalues传递给callable,并使用reference_wrappers,占位符和绑定表达式做出不必要的魔法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |