2012-11-28 86 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

相關問題