加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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,占位符和绑定表达式做出不必要的魔法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读