2016-07-06 31 views
0

我相信這肯定是一個常見問題,所以如果只是我的搜索技能失敗了,在重載的類方法上使用std :: bind()

我試圖做到這一點沒有提升,因爲功能存在於C + + 11,我是標準的粉絲。

我想使用std :: bind()從外部庫中包裝一個類的方法。 (特別是:asio :: io_service :: run()) 不幸的是,這個方法被重載,導致std :: bind()混淆。

最小的測試案例來證明這個問題:

#include <functional> // std::bind 

class Test{ 
public: 
    void method(){} 
    void method(int i){} 
}; 

int main(int argc, char * argv[]) { 
    Test test_instance; 
    auto bound_thing_1 = std::bind(Test::method, test_instance); 
    return 0; 
} 

和編譯:

[email protected]:/tmp/bind_test$ gcc -v 
Using built-in specs. 
COLLECT_GCC=gcc 
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper 
Target: x86_64-linux-gnu 
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.3.1-14ubuntu2.1' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 
Thread model: posix 
gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) 
[email protected]:/tmp/bind_test$ /usr/bin/g++ -Wall -std=c++11 ./main.c -o test.bin 
./main.c: In function ‘int main(int, char**)’: 
./main.c:12:61: error: no matching function for call to ‘bind(<unresolved overloaded function type>, Test&)’ 
    auto bound_thing_1 = std::bind(Test::method, test_instance); 
                  ^
In file included from /usr/include/c++/5/memory:79:0, 
       from /usr/include/asio/detail/addressof.hpp:21, 
       from /usr/include/asio/detail/handler_alloc_helpers.hpp:19, 
       from /usr/include/asio/detail/bind_handler.hpp:19, 
       from /usr/include/asio/detail/wrapped_handler.hpp:18, 
       from /usr/include/asio/io_service.hpp:24, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/c++/5/functional:1462:5: note: candidate: template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) 
    bind(_Func&& __f, _BoundArgs&&... __args) 
    ^
/usr/include/c++/5/functional:1462:5: note: template argument deduction/substitution failed: 
./main.c:12:61: note: couldn't deduce template parameter ‘_Func’ 
    auto bound_thing_1 = std::bind(Test::method, test_instance); 
                  ^
In file included from /usr/include/c++/5/memory:79:0, 
       from /usr/include/asio/detail/addressof.hpp:21, 
       from /usr/include/asio/detail/handler_alloc_helpers.hpp:19, 
       from /usr/include/asio/detail/bind_handler.hpp:19, 
       from /usr/include/asio/detail/wrapped_handler.hpp:18, 
       from /usr/include/asio/io_service.hpp:24, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/c++/5/functional:1490:5: note: candidate: template<class _Result, class _Func, class ... _BoundArgs> typename std::_Bindres_helper<_Result, _Func, _BoundArgs>::type std::bind(_Func&&, _BoundArgs&& ...) 
    bind(_Func&& __f, _BoundArgs&&... __args) 
    ^
/usr/include/c++/5/functional:1490:5: note: template argument deduction/substitution failed: 
./main.c:12:61: note: couldn't deduce template parameter ‘_Result’ 
    auto bound_thing_1 = std::bind(Test::method, test_instance); 

所以有問題(我把它解釋)是的std ::綁定不知道是否使用method()method(int)

我的下一步就是明確地告訴的std :: bind()的哪一種方法:

#include <functional> // std::bind 

class Test{ 
public: 
    void method(){} 
    void method(int i){} 
}; 

int main(int argc, char * argv[]) { 
    Test test_instance; 
    // auto bound_thing_1 = std::bind(Test::method, test_instance); 
    auto bound_thing_2 = std::bind(static_cast<void(Test::*)(void)>(&Test::method), test_instance); 
    return 0; 
} 

此建立正確。 (!耶)

所以現在我嘗試使用我的期望庫採用同樣的邏輯: http://think-async.com/Asio/asio-1.10.6/doc/asio/reference/io_service/run.html

#include <asio.hpp> 
#include <thread>   // std::thread 
#include <functional> // std::bind 

int main(int argc, char * argv[]) { 
    asio::io_service io_service_instance; 
    auto bound_thing_3 = std::bind(static_cast<std::size_t(asio::io_service::*)(void)>(&asio::io_service::run), io_service_instance); 

    std::thread mythread(bound_thing_3) 
    return 0; 
} 

和編譯失敗:

[email protected]:/tmp/bind_test$ /usr/bin/g++ -Wall -std=c++11 ./main.c -o test.bin -lpthread 
In file included from /usr/include/c++/5/functional:55:0, 
       from /usr/include/c++/5/memory:79, 
       from /usr/include/asio/detail/addressof.hpp:21, 
       from /usr/include/asio/detail/handler_alloc_helpers.hpp:19, 
       from /usr/include/asio/detail/bind_handler.hpp:19, 
       from /usr/include/asio/detail/wrapped_handler.hpp:18, 
       from /usr/include/asio/io_service.hpp:24, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/c++/5/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = asio::io_service; long unsigned int _Idx = 0ul; _Head = asio::io_service]’: 
/usr/include/c++/5/tuple:369:49: required from ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head>&&) [with long unsigned int _Idx = 0ul; _Head = asio::io_service]’ 
/usr/include/c++/5/tuple:484:17: required from ‘std::_Bind<_Functor(_Bound_args ...)>::_Bind(std::_Bind<_Functor(_Bound_args ...)>&&) [with _Functor = std::_Mem_fn<long unsigned int (asio::io_service::*)()>; _Bound_args = {asio::io_service}]’ 
./main.c:16:130: required from here 
/usr/include/c++/5/tuple:115:42: error: use of deleted function ‘asio::io_service::io_service(const asio::io_service&)’ 
    : _M_head_impl(std::forward<_UHead>(__h)) { } 
             ^
In file included from /usr/include/asio/basic_io_object.hpp:19:0, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/io_service.hpp:184:7: note: ‘asio::io_service::io_service(const asio::io_service&)’ is implicitly deleted because the default definition would be ill-formed: 
class io_service 
    ^
In file included from /usr/include/asio/io_service.hpp:23:0, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/detail/noncopyable.hpp:31:3: error: ‘asio::detail::noncopyable::noncopyable(const asio::detail::noncopyable&)’ is private 
    noncopyable(const noncopyable&); 
^
In file included from /usr/include/asio/basic_io_object.hpp:19:0, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/io_service.hpp:184:7: error: within this context 
class io_service 
    ^
In file included from /usr/include/c++/5/memory:79:0, 
       from /usr/include/asio/detail/addressof.hpp:21, 
       from /usr/include/asio/detail/handler_alloc_helpers.hpp:19, 
       from /usr/include/asio/detail/bind_handler.hpp:19, 
       from /usr/include/asio/detail/wrapped_handler.hpp:18, 
       from /usr/include/asio/io_service.hpp:24, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/c++/5/functional: In instantiation of ‘std::_Bind<_Functor(_Bound_args ...)>::_Bind(std::_Bind<_Functor(_Bound_args ...)>&&) [with _Functor = std::_Mem_fn<long unsigned int (asio::io_service::*)()>; _Bound_args = {asio::io_service}]’: 
./main.c:16:130: required from here 
/usr/include/c++/5/functional:1120:78: note: synthesized method ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(std::tuple< <template-parameter-1-1> >&&) [with _Elements = {asio::io_service}]’ first required here 
     : _M_f(std::move(__b._M_f)), _M_bound_args(std::move(__b._M_bound_args)) 
                      ^
In file included from /usr/include/c++/5/functional:55:0, 
       from /usr/include/c++/5/memory:79, 
       from /usr/include/asio/detail/addressof.hpp:21, 
       from /usr/include/asio/detail/handler_alloc_helpers.hpp:19, 
       from /usr/include/asio/detail/bind_handler.hpp:19, 
       from /usr/include/asio/detail/wrapped_handler.hpp:18, 
       from /usr/include/asio/io_service.hpp:24, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/c++/5/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with long unsigned int _Idx = 0ul; _Head = asio::io_service]’: 
/usr/include/c++/5/tuple:357:21: required from ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(const _Head&) [with long unsigned int _Idx = 0ul; _Head = asio::io_service]’ 
/usr/include/c++/5/tuple:473:33: required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(const _Elements& ...) [with _Elements = {asio::io_service}]’ 
/usr/include/c++/5/functional:1114:70: required from ‘std::_Bind<_Functor(_Bound_args ...)>::_Bind(_Functor&&, _Args&& ...) [with _Args = {asio::io_service&}; _Functor = std::_Mem_fn<long unsigned int (asio::io_service::*)()>; _Bound_args = {asio::io_service}]’ 
/usr/include/c++/5/functional:1468:42: required from ‘typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) [with _Func = long unsigned int (asio::io_service::*)(); _BoundArgs = {asio::io_service&}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind<std::_Mem_fn<long unsigned int (asio::io_service::*)()>(asio::io_service)>]’ 
./main.c:16:130: required from here 
/usr/include/c++/5/tuple:108:25: error: use of deleted function ‘asio::io_service::io_service(const asio::io_service&)’ 
     : _M_head_impl(__h) { } 

問題: 誰能幫助我(或指向我的信息來源)瞭解這裏發生了什麼。 我懷疑這個問題是與static_cast的「靜態」性質有關的...

這個可能的解決方案使用了lambda函數,但我很想聽聽關於它是否是「正確」的方式的東西。 我個人也覺得這更容易解析:

#include <asio.hpp> 
#include <thread>   // std::thread 
#include <functional> // std::bind 

int main(int argc, char * argv[]) { 
    asio::io_service io_service_instance; 

    auto bound_thing_4 = [&](){ 
    return io_service_instance.run(); 
    }; 
    std::thread mythread(bound_thing_4); 
    return 0; 
} 

[編輯]解決方案:

出現ASIO的情況下:: io_service對象不喜歡被複制:

#include <asio.hpp> 

int main(int argc, char * argv[]) { 
    asio::io_service io_service_instance; 
    auto io_service_instance_2 = io_service_instance; 

    return 0; 
} 

給編譯器錯誤:

[email protected]:/tmp/bind_test$ /usr/bin/g++ -Wall -std=c++11 ./main.c -o test.bin -lpthread 
./main.c: In function ‘int main(int, char**)’: 
./main.c:5:32: error: use of deleted function ‘asio::io_service::io_service(const asio::io_service&)’ 
    auto io_service_instance_2 = io_service_instance; 
           ^
In file included from /usr/include/asio/basic_io_object.hpp:19:0, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/io_service.hpp:184:7: note: ‘asio::io_service::io_service(const asio::io_service&)’ is implicitly deleted because the default definition would be ill-formed: 
class io_service 
    ^
In file included from /usr/include/asio/io_service.hpp:23:0, 
       from /usr/include/asio/basic_io_object.hpp:19, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/detail/noncopyable.hpp:31:3: error: ‘asio::detail::noncopyable::noncopyable(const asio::detail::noncopyable&)’ is private 
    noncopyable(const noncopyable&); 
^
In file included from /usr/include/asio/basic_io_object.hpp:19:0, 
       from /usr/include/asio/basic_socket.hpp:20, 
       from /usr/include/asio/basic_datagram_socket.hpp:20, 
       from /usr/include/asio.hpp:19, 
       from ./main.c:1: 
/usr/include/asio/io_service.hpp:184:7: error: within this context 
class io_service 

所以工作溶液包括使b Ÿ參考,而不是複製(按ecatmur的答案):

#include <asio.hpp> 
#include <thread>   // std::thread 
#include <functional> // std::bind 

int main(int argc, char * argv[]) { 
    asio::io_service io_service_instance; 
    auto bound_thing_3 = std::bind(
     static_cast<std::size_t(asio::io_service::*)(void)>(&asio::io_service::run), 
     std::ref(io_service_instance)); 

    std::thread mythread(bound_thing_3); 
    return 0; 
} 

回答

2

如果你想std::bind參考捕捉它的參數,你需要使用std::reference_wrapper

auto bound_thing_3 = std::bind(static_cast<std::size_t(asio::io_service::*)(void)>(&asio::io_service::run), 
    std::ref(io_service_instance)); 
+0

啊。有趣。我相信與std :: bind()通過引用傳遞是可選的... 所以這裏的問題似乎是asio :: io_service的實例不喜歡被複制。 我會給我的問題添加證明。 – mrdunk