c++ - 在 C++11 中绑定(bind)函数参数

标签 c++ templates c++11 variadic-templates

我想一般地“挑选”函数调用,以便它们可以在以后执行。这些函数的返回类型将始终为 void(目前)。像这样:

template<typename F, typename... Args>
std::function<void()> 
pickle(F function, Args&&... args) {
    return std::bind(F, args...);
}

问题是,如果 args 包含一个 const 引用,std::bind 会尝试复制构造该值,如果类型缺少复制构造函数。如何以使用 std::ref 进行左值引用并使用普通 std::forward 进行左值引用的方式转发参数?

例子

#include <functional>

class NonCopyable {
public:

    NonCopyable() {}

    NonCopyable(const NonCopyable&) = delete;
};

template<typename F, typename... Args>
std::function<void()>
pickle(F function, Args&&... args)
{
    return std::bind(function, std::forward<Args>(args)...);
}

int main()
{
    NonCopyable obj;
    auto f = pickle(
        [](const NonCopyable&) {},
        obj
    );
    return 0;
}

上面的代码片段无法编译,提示删除了复制构造函数。 (我在这里使用 forward 是因为有人建议它,但似乎已经删除了他们的答案)。

最佳答案

重载,是的。

// also does the correct thing for `T const`
template<class T>
std::reference_wrapper<T> maybe_ref(T& v, int){ return std::ref(v); }

// just forward rvalues along
template<class T>
T&& maybe_ref(T&& v, long){ return std::forward<T>(v); }

template<typename F, typename... Args>
std::function<void()> 
pickle(F function, Args&&... args) {
    return std::bind(function, maybe_ref(std::forward<Args>(args), 0)...);
}

int/long 参数和 0 参数为发现重载不明确的编译器消除了左值大小写的歧义,并且否则会造成任何伤害。

关于c++ - 在 C++11 中绑定(bind)函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15501301/

相关文章:

c++ - 重载方法覆盖 : Is there any simplification?

c++ - Variadic 模板双端包解决方法

c++ - 为什么 C++ 模板不会导致多重定义错误?

c++ - 取消引用指向其类内对象的指针

c++ - 复合模式 : Copy tree structure

c++ - CRTP编译错误

c++ - 删除后 C++ 中的指针

c++ - 使用(自定义)GCC 4.x 或 5.x 时,Boost 构建无法通过 C++11 功能检查

c++ - 如何 typedef 具有未指定大小的 std::array?

c++ - 给类(class)成员打分