c++ - using std::bind() on overloaded class method -


this question has answer here:

i'm sure must common issue apologies if it's search skills failing.

i'm trying without boost because functionality exists in c++11 , i'm fan of standards.

i'm trying use std::bind() wrap method in class external library. (specifically: asio::io_service::run() ) unfortunately method overloaded confuses std::bind().

minimal test case demonstrate issue:

#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; } 

and compile:

duncan@casper:/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)  duncan@casper:/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 call ‘bind(<unresolved overloaded function type>, test&)’    auto bound_thing_1 = std::bind(test::method, test_instance);                                                              ^ in file included /usr/include/c++/5/memory:79:0,                  /usr/include/asio/detail/addressof.hpp:21,                  /usr/include/asio/detail/handler_alloc_helpers.hpp:19,                  /usr/include/asio/detail/bind_handler.hpp:19,                  /usr/include/asio/detail/wrapped_handler.hpp:18,                  /usr/include/asio/io_service.hpp:24,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./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 /usr/include/c++/5/memory:79:0,                  /usr/include/asio/detail/addressof.hpp:21,                  /usr/include/asio/detail/handler_alloc_helpers.hpp:19,                  /usr/include/asio/detail/bind_handler.hpp:19,                  /usr/include/asio/detail/wrapped_handler.hpp:18,                  /usr/include/asio/io_service.hpp:24,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./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); 

so problem there (as interpret it) std::bind not know whether use method() or method(int).

my next step explicitly tell std::bind() method:

#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; } 

this builds correctly. (yay!)

so try apply same logic using desired library: 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; } 

and compile fails:

duncan@casper:/tmp/bind_test$ /usr/bin/g++ -wall -std=c++11 ./main.c -o test.bin -lpthread in file included /usr/include/c++/5/functional:55:0,                  /usr/include/c++/5/memory:79,                  /usr/include/asio/detail/addressof.hpp:21,                  /usr/include/asio/detail/handler_alloc_helpers.hpp:19,                  /usr/include/asio/detail/bind_handler.hpp:19,                  /usr/include/asio/detail/wrapped_handler.hpp:18,                  /usr/include/asio/io_service.hpp:24,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./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 ‘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 ‘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 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 /usr/include/asio/basic_io_object.hpp:19:0,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/io_service.hpp:184:7: note: ‘asio::io_service::io_service(const asio::io_service&)’ implicitly deleted because default definition ill-formed:  class io_service        ^ in file included /usr/include/asio/io_service.hpp:23:0,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/detail/noncopyable.hpp:31:3: error: ‘asio::detail::noncopyable::noncopyable(const asio::detail::noncopyable&)’ private    noncopyable(const noncopyable&);    ^ in file included /usr/include/asio/basic_io_object.hpp:19:0,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/io_service.hpp:184:7: error: within context  class io_service        ^ in file included /usr/include/c++/5/memory:79:0,                  /usr/include/asio/detail/addressof.hpp:21,                  /usr/include/asio/detail/handler_alloc_helpers.hpp:19,                  /usr/include/asio/detail/bind_handler.hpp:19,                  /usr/include/asio/detail/wrapped_handler.hpp:18,                  /usr/include/asio/io_service.hpp:24,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./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 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 /usr/include/c++/5/functional:55:0,                  /usr/include/c++/5/memory:79,                  /usr/include/asio/detail/addressof.hpp:21,                  /usr/include/asio/detail/handler_alloc_helpers.hpp:19,                  /usr/include/asio/detail/bind_handler.hpp:19,                  /usr/include/asio/detail/wrapped_handler.hpp:18,                  /usr/include/asio/io_service.hpp:24,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./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 ‘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 ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(const _elements& ...) [with _elements = {asio::io_service}]’ /usr/include/c++/5/functional:1114:70:   required ‘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 ‘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 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) { } 

the question: can me (or point me towards source of information) understand what's going on here. suspect problem related "static" nature of static_cast...

this possible solution using lambda function works i'd interested hear opinions on whether it's "correct" way things. find easier parse:

#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; } 

[edit] solution:

it appears instances of asio::io_service not copied:

#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; } 

gives compiler error:

duncan@casper:/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 /usr/include/asio/basic_io_object.hpp:19:0,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/io_service.hpp:184:7: note: ‘asio::io_service::io_service(const asio::io_service&)’ implicitly deleted because default definition ill-formed:  class io_service        ^ in file included /usr/include/asio/io_service.hpp:23:0,                  /usr/include/asio/basic_io_object.hpp:19,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/detail/noncopyable.hpp:31:3: error: ‘asio::detail::noncopyable::noncopyable(const asio::detail::noncopyable&)’ private    noncopyable(const noncopyable&);    ^ in file included /usr/include/asio/basic_io_object.hpp:19:0,                  /usr/include/asio/basic_socket.hpp:20,                  /usr/include/asio/basic_datagram_socket.hpp:20,                  /usr/include/asio.hpp:19,                  ./main.c:1: /usr/include/asio/io_service.hpp:184:7: error: within context  class io_service 

so working solution involves passing reference instead of copying (as per ecatmur's answer):

#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; } 

if want std::bind capture argument reference, need use 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)); 

Comments

Popular posts from this blog

sequelize.js - Sequelize group by with association includes id -

android - Robolectric "INTERNET permission is required" -

java - Android raising EPERM (Operation not permitted) when attempting to send UDP packet after network connection -