2011-09-13 62 views
1
#include <functional> 
#include <memory> 
#include <iostream> 

using namespace std; 

class Foo 
{ 
public: 
    void Bar() { std::cout << "Foo::Bar" << std::endl; } 
}; 

int main() 
{ 
    shared_ptr<Foo> foo(new Foo); 
    function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1)); 
    function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1)); 
    return 0; 
} 

第二個綁定語句的GCC對象被分配給帶有shared_ptr簽名的函數對象。這是錯誤輸出。爲什麼這個代碼片段用VS2010編譯而不是GCC 4.5.2?

/usr/include/c++/4.5/functional:2103|6|instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::_Bind(std::_Placeholder<1>)>, _Res = void, _ArgTypes = {std::shared_ptr}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function)>::_Useless]’| /home/craig/work/litd/test/main.cpp:29|97|instantiated from here| /usr/include/c++/4.5/functional|1713|error: no match for call to ‘(std::_Bind(std::_Placeholder<1>)>) (std::shared_ptr)’| ||=== Build finished: 1 errors, 0 warnings ===|

編輯: 更神祕,當我改變包括頭部他們TR1等價物,它編譯。

#include <tr1/functional> 
#include <tr1/memory> 
#include <iostream> 

using namespace std::tr1; 

class Foo 
{ 
public: 
    void Bar() { std::cout << "Foo::Bar" << std::endl; } 
}; 

int main() 
{ 
    shared_ptr<Foo> foo(new Foo); 
    function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1)); 
    function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1)); 
    return 0; 
} 
+0

也可能會發布實際的錯誤消息。 – sbi

+0

它可能需要模板的幫助'std :: function )> f2(bind(&Foo :: Bar,std :: placeholders :: _ 1));''也許? – AJG85

+0

還是不開心。 /home/craig/work/litd/test/main.cpp||函數'int main()':| /home/craig/work/litd/test/main.cpp|29|error:參數聲明中typedef聲明無效| /home/craig/work/litd/test/main.cpp|29|error:在'f2'之前預期'::'| /home/craig/work/litd/test/main.cpp|29|error:'std :: function :: f2'has not been declared | /home/craig/work/litd/test/main.cpp|29|error:expected')'before'('token | || ===構建完成:4個錯誤,0個警告=== | – Craig

回答

0

函數將期望->*被重載使用指向成員的指針。我相信shared_ptr不提供此功能。 TR1規範可能要求專門化,但C++ 11可能沒有。在Visual Studio中,C++ 11 shared_ptr被定義爲它們的TR1版本,這將解釋不同之處。

+0

I看了兩個shared_ptr的g ++&vs2010實現,而且都沒有實現operator - > *。 – Craig

+0

@Craig:我還提到了專業化的可能性 – Puppy

1

它看起來像用g ++的執行std::function也許std::bind,這取決於你是否可以通過調用與bind(&Foo::Bar, placeholders::_1)返回foo對象中的錯誤;如果這個工程:

auto fn2 = bind(&Foo::Bar, placeholders::_1); 
fn2(foo); 

那就似乎是G ++的std::function實現是不完整的。否則,看起來std::bind的實施是不完整的。

[20.8.9.1.2]功能模板bind狀態:

template<class F, class... BoundArgs> 
    unspecified bind(F&& f, BoundArgs&&... bound_args); 

...

Returns: A forwarding call wrapper g with a weak result type (20.8.2). The effect of g(u1, u2, ..., uM) shall be INVOKE(fd, v1, v2, ..., vN, result_of::type)

[20.8.2]要求的國家:

Define INVOKE(f, t1, t2, ..., tN) as follows:

(t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T ;

((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item;

...

當綁定&Foo::Bar,返回的 「轉發調用包裝」 需要一個參數u1。請撥打電話U1。在[20.8.9.1.2]中進一步指出,因爲BoundArgs中的第一個模板參數類型是_1佔位符類型,所以類型V1U1&&

應該允許將std::shared_ptr<Foo>傳遞給由bind(&Foo::Bar, placeholders::_1)返回的轉發呼叫包裝,因爲[20.8.2]的情況2適用。

編輯:我在Windows(MinGW)上使用與你同樣的版本的g ++ 4.5.2。對我來說,下面的編譯就好:

#include <functional> 
#include <memory> 
#include <iostream> 

using namespace std; 

class Foo 
{ 
public: 
    void Bar() { std::cout << "Foo::Bar" << std::endl; } 
}; 

int main() 
{ 
    shared_ptr<Foo> foo(new Foo); 
    function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1)); 
    //function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1)); 
    auto fn2 = bind(&Foo::Bar, placeholders::_1); 
    fn2(foo); 
    return 0; 
} 

因此,它似乎是G ++的實施std::function這是難辭其咎的。

EDIT2:以下失敗:

auto fn2 = bind(&Foo::Bar, placeholders::_1); 
fn2(std::shared_ptr<Foo>(foo)); 

SO7408263.cpp:19:31: error: no match for call to '(std::_Bind(std::_Placeholder<1>)>) (std::shared_ptr)'

也許是std::bind畢竟。

+0

感謝您的回答。奇怪的是,它不能在我的Ubuntu上編譯可能在每個平臺上打破不同的位? – Craig

+0

@Craig:'fn2(foo);'不能在你的Ubuntu設置上編譯?奇怪,我認爲MinGW的libstdC++版本是未修改的。 –

相關問題