C++11/14 调用解决方法

标签 c++ c++11 c++14

我需要在某些 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, 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::forward<Fn>(f)(std::forward<Args>(args)...)))
{
    return std::forward<Fn>(f)(std::forward<Args>(args)...);
}

这基本上是 N4169 中提出的最小实现. (真正的标准库实现者不会这样做,因为将 INVOKE 功能集中在一个地方并让其他各个部分调用它更易于维护。)

顺便说一下,使用std::bind 是完全错误的。它复制/移动所有参数,将它们作为左值传递给可调用对象,并使用 reference_wrappers、占位符和绑定(bind)表达式执行不需要的魔法。

关于C++11/14 调用解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38288042/

相关文章:

c++ - Solaris 上的空核心文件

c++ - OpenGL ES 3.1 - 无法使用 glTexImage2D 创建不可变纹理

c++ - 如何在 VC++ 中更改 __stdcall 的导出名称修饰?

c++ - 专门化采用通用引用参数的函数模板

c++ - 检查一个类是否具有给定签名的成员函数

c++ - 什么是单遍算法

c++ - 如何为包含 std::vector 的类实现operator[]

c++ - 与先前参数类型匹配的参数包

c++ - 如何在 C++ 中返回 unique_ptr 列表?

C++11 lambda函数对象成员