为啥 std::bind 不能作为参数包的参数?

Posted

技术标签:

【中文标题】为啥 std::bind 不能作为参数包的参数?【英文标题】:Why std::bind can't be param of parameters pack?为什么 std::bind 不能作为参数包的参数? 【发布时间】:2013-11-19 02:55:37 【问题描述】:

我想使用参数包,但发现问题。 一些代码:

template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))

    auto f11 = std::bind(func, args...);
    f11();


void print(const char* string)

    std::cout << string << std::endl;

这一切都很好:

    f([] (const char* additional, const char* more) 
        std::cout << "hello ( " << additional << ", " << more << " )" << std::endl;
    , "additional text", "and one more");

    auto printFunction = std::bind(&print, std::placeholders::_1);

    printFunction("hello from print bind");

    f(print, "hello from print directly");

但如果我想将 std::function 提供给参数包:

f([] (std::function<void(const char*)> printParamFunc) 
 printParamFunc("hello from print from std::function");
, printFunction);

应用程序不再编译。

那么,在pack中使用函数作为参数有什么问题呢?

谢谢。

更新: 如果将 f 的代码更改为:

template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))

    func(args...);

效果很好,但我不想在这里执行这个函数,我想创建函数并像参数一样传递它。

更新 2: 代码执行示例:http://ideone.com/gDjnPq

更新3: 清除编译错误代码:http://ideone.com/50z7IN

【问题讨论】:

然后添加最重要的部分。尝试破译它并阅读它想说的内容。如果没有错误,没有人可以帮助您。 你能把sscce.org放在ideone之类的东西上并添加一个链接,以便我们可以看到生成的错误消息吗? 如果不是auto,你可以让它工作,给printFunction输入std::function&lt;void(const char*)&gt;。我不知道这是为什么。来自 clang 的错误消息表明它无法推断出 _Result 类型的绑定表达式。 这里是上面的一个 sscce:ideone.com/50z7IN -- 我还不知道为什么它不能编译,但它就是! Answer is here一些具体的std::bind。 【参考方案1】:

我现在对情况有了一些了解。

此代码可以追溯问题:

void print(const char* string)

    std::cout << string << std::endl;


int main(int argc, char ** argv)

    auto lambda = [] (std::function< void ( const char * ) > printParamFunc) 
        printParamFunc("hello from lambda!");
    ;

    std::bind(lambda, std::bind(print, std::placeholders::_1))();

嵌套的 std::bind 试图评估并失败,将 _1 转换为 const char *。它是 std::bind 特有的。

我们需要 boost::bind::protect 的类比——存储其他函子的函子——这是解决问题:

template <class F>
struct lazy_evaluate 
    typedef typename F::result_type T;

    explicit lazy_evaluate(F f) : f_(f) 

    template <class... Args>
    T operator()(Args&&... args) 
    
        f_(std::forward<Args>(args)...);
    

private:
    F f_; 
;

template <class F>
lazy_evaluate<F> lazy(F f)

    return lazy_evaluate<F>(f);

嵌套的 std::bind 现在看起来像:

std::bind(lambda, lazy(std::bind(print, std::placeholders::_1)))();

而且效果很好。

【讨论】:

以上是关于为啥 std::bind 不能作为参数包的参数?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中,数组名作为函数参数,属于啥传递,为啥?

第11课 std::bind和std::function_std::bind绑定器

C++11 std::bind std::function 变参函数

C++11 std::bind std::function 变参函数

为啥数组不能作为函数参数传递?

C++11 std::bind函数,std::function函数