c++ - std::bind 和完美转发

标签 c++ c++11 perfect-forwarding stdbind

以下代码无法编译:

#include <functional>

template<class ...Args>
void invoke(Args&&... args)
{
}

template<class ...Args>
void bind_and_forward(Args&&... args)
{
    auto binder = std::bind(&invoke<Args...>, std::forward<Args>(args)...);
    binder();
}

int main()
{
    int a = 1;
    bind_and_forward(a, 2);
}

如果我没理解错的话,原因如下:std::bind复制它的参数,当binderoperator() 被调用时,它将所有绑定(bind)参数作为 lvalues 传递 - 甚至那些输入 bind 的参数作为 rvalues。但是 invoke 是为原始参数实例化的,它不能接受 binder 试图传递给它的内容。

这个问题有解决办法吗?

最佳答案

你的理解是正确的- bind复制它的参数。所以你必须提供正确的重载 invoke()将在左值上调用:

template<class ...Args>
void bind_and_forward(Args&&... args)
{
    auto binder = std::bind(&invoke<Args&...>, std::forward<Args>(args)...);
                                    ^^^^^^^^
    binder();
}

这适用于大多数类型。 [func.bind.bind] 中为 operator() 列举了一些异常(exception)情况, 其中Arg&是不够的。正如您所指出的,其中之一是 std::reference_wrapper<T> .我们可以通过替换 Args& 来解决这个问题上面的用法与类型特征。通常,我们只是添加一个左值引用,但对于 reference_wrapper<T> ,我们只想要 T& :

template <typename Arg>
struct invoke_type 
: std::add_lvalue_reference<Arg> { };

template <typename T>
struct invoke_type<std::reference_wrapper<T>> {
    using type = T&;
};

template <typename T>
using invoke_type_t = typename invoke_type<T>::type;

将其重新插入原始解决方案,我们得到适用于 reference_wrapper 的东西也是:

template<class ...Args>
void bind_and_forward(Args&&... args)
{
    auto binder = std::bind(&invoke<invoke_type_t<Args>...>, 
                            //      ^^^^^^^^^^^^^^^^^^^
                            std::forward<Args>(args)...);
    binder();
}

当然,如果Arg之一是一个占位符,无论如何都行不通。如果它是绑定(bind)表达式,您还必须编写其他内容。

关于c++ - std::bind 和完美转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30968573/

相关文章:

c++ - 在 64 位可执行文件中执行 64 位计算

c++ - 可 move 但不可复制的对象:按值传递还是按引用传递?

c++ - 成员函数的 std::forward 和 ref 限定符

c++ - opengl gl读取像素

c++ - 当我们在 C++ 中说 "initialize the object"时,它实际上意味着什么?

c++ - 错误 C1189 : #error : WINDOWS. H 已经包括在内。 MFC 应用程序不得 #include <windows.h>"**

c++ - 如何在 Eclipse 中启用 C++11 支持?

c++ - 向用户询问 2 个数字时发生无限循环

c++ - std::forward 模板和非模板函数中的测试

templates - 完美转发模板参数包到emplace_back - 编译失败