2014-10-03 65 views
1

請有人幫助解釋爲什麼在OS X上使用Xcode 5.1編譯以下代碼時出現錯誤。 Apple LLVM 5.1版(clang-503.0.40)(基於在LLVM 3.4svn上)。構建std :: function向量時編譯器出錯

#include <vector> 
#include <functional> 

void func1(const std::string& value) 
{ 
    // ... 
} 

void func2(const std::string& value, int min, int max) 
{ 
    // ... 
} 

class X 
{ 
public: 
    void x1(const std::string& value) 
    { 
     // ... 
    } 

    void x2(const std::string& value, int min, int max) 
    { 
     // ... 
    } 
}; 

const std::vector<std::function<void(std::string)>> functions 
{ 
    func1, 
    std::bind(func2, std::placeholders::_1, 5, 6), 
    std::mem_fn(&X::x1),        // compiler error 
}; 

報告該錯誤是:

no matching constructor for initialization of 'const std::vector<std::function<void (std::string)> >' 
const std::vector<std::function<void(std::string)>> functions 

此外,我想X :: X2添加到載體。我會怎麼做?

謝謝。

+4

成員函數需要一個對象進行操作,他們的簽名是不兼容與'void(std :: string)'在你的情況。你可以使用bind來使它工作,但你需要一個實例。 – Mat 2014-10-03 08:26:07

+0

@Mat請添加此作爲答案。 – balajeerc 2014-10-03 08:30:53

+0

@Mat請你詳細說明。 – ksl 2014-10-03 08:33:05

回答

1

std::mem_fn做什麼,它返回一些未指定對象可調用與相同類型傳遞該成員函數或成員變量的附加第一參數的指針或引用類型的(或甚至一個智能指針類型)屬於(所有其他參數都被轉發)。這意味着你可以是對象存儲在一個函數包裝象下面這樣:

std::function<void(X*,const std::string&)> f = std::mem_fn(&X::x1); 

,然後用一個實際的參數調用它:

X x{}; 
f(&x, "foo"); // or std::mem_fn(&X::x1)(&x, "foo"); 

是一樣的:

(&x)->x1("foo"); 

在換句話說,在將該可調用對象存儲在的std::function<void(const std::string&)>中時,這很可能不是您想要的。而不是添加額外的第一個參數,你倒是應該與該功能將被調用爲它的上下文綁定它:

X x{}; // object in context of which the function will be called 

const std::vector<std::function<void(std::string)>> functions 
{ 
    func1, 
    std::bind(func2, std::placeholders::_1, 5, 6), 
    std::bind(&X::x1, &x, std::placeholders::_1), 
// ~~~~~~~~^ ~~~~~^ ~^   ~~~~~~~~~~^ 
//  bind function with object x and actual argument to be forwarded 
}; 

DEMO

+0

非常感謝。 – ksl 2014-10-03 12:27:43