2012-11-28 74 views
1

为什么下面代码中嵌套的std::bind没有被任何主编译器(VS2010/2012,gcc,clang)隐式转换为std::function<void()>?这是标准行为还是错误?为什么这个std :: bind没有转换成std :: function?

#include <functional> 

void bar(int, std::function<void()>) { } 
void foo() { } 

int main() 
{ 
    std::function<void(int, std::function<void()>)> func; 
    func = std::bind(bar, 5, std::bind(foo)); 

    std::cin.get(); 
    return 0; 
} 
+1

因为嵌套的绑定表达式被热切地评估。实际上,你正在做类似于'std :: bind(bar,5,void)'的东西,这是无意义的。 – ildjarn

+1

这并不回答这个问题,但是这个:'func = std :: bind(bar,5,foo);'按照你的预期工作。 – 111111

+3

你试图实现什么? 'bar'可以直接指定给'func',通过绑定你正在创建一个可以不带任何参数(或任何组合或参数)调用的函子的参数。使用当前代码(假设它已编译)'func'必须用int和'std :: function '调用,两个参数都会被忽略,并且会触发'bar(5,foo) ... –

回答

4

这在boost documentation说明:

内绑定表达式进行求值,在未指定的顺序, 当功能对象被称为外绑定之前;当外部结合是 评估时, 评估的结果在它们的位置被替换。在上面的例子中,当函数对象被称为 和参数列表(x)时,bind(g,_1)(x)首先被计算, 产生g(x),然后bind(f,g(x) )(x)进行评估,得到最终结果f(g(x))。

加速甚至提供protect,以防止这样的评价:

#include <boost/bind/protect.hpp> 
... 
func = std::bind(bar, 5, boost::protect(std::bind(foo))); 

然而,调用func你必须(指出了这一点得益于David Rodríguez - dribeas)提供两个参数就是这样,所以这个例子肯定是不好:

func(1, std::function<void()>()); 
+0

'boost :: protect'和'std :: bind'在一起玩的很好吗?我没有尝试,但我认为他们不会... – ildjarn

+0

@ildjam:他们做 –

+0

@ildjarn:'boost :: protect'真的没什么特别的,它只是一个完美的转发仿函数,如果你愿意的话。有什么特别的是'std :: bind'的返回类型,对此['std :: is_bind_expression'](http://en.cppreference.com/w/cpp/utility/functional/is_bind_expression)为真。根据这个特点,一个仿函数要么被急切地评估,要么正常传递。对于'boost :: protect'的结果,'is_bind_expression'从'false_type'派生。 – Xeo

相关问题