Strange behavior change in boost :: bind / boost :: function from 1.55

I tried to compile a project that was written against Boost 1.55 against the new Boost 1.63, and I came across a really strange error before bind / function . Here's a complete, simplified test case:

 #include <boost/bind.hpp> #include <boost/function.hpp> template < typename Arg1 = int, typename Arg2 = int, typename Arg3 = int > class foo { public: using function_t = boost::function3< void, Arg1, Arg2, Arg3 >; void set_function( function_t f ) { func_ = f; } private: function_t func_; }; class bar { public: bar() { foo_.set_function( boost::bind( &bar::func, this, _1, _2 ) ); } private: void func( int const&, int& ) {} foo< int, int > foo_; }; int main() { bar x; return 0; } 

... and some snippets of errors that I get:

 /usr/include/boost/bind/bind.hpp:398:35: error: no match for call to '(boost::_mfi::mf2<void, bar, const int&, int&>) (bar*&, int, int)' /usr/include/boost/bind/mem_fn_template.hpp:278:7: note: candidate: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T*, A1, A2) const [with R = void; T = bar; A1 = const int&; A2 = int&] <near match> /usr/include/boost/bind/mem_fn_template.hpp:278:7: note: conversion of argument 3 would be ill-formed: /usr/include/boost/bind/bind.hpp:398:35: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int' /usr/include/boost/bind/mem_fn_template.hpp:283:25: note: candidate: template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(U&, A1, A2) const [with U = U; R = void; T = bar; A1 = const int&; A2 = int&] /usr/include/boost/bind/mem_fn_template.hpp:283:25: note: template argument deduction/substitution failed: /usr/include/boost/bind/bind.hpp:398:35: note: cannot convert '(& a)->boost::_bi::rrlist3<int, int, int>::operator[](boost::_bi::storage3<boost::_bi::value<bar*>, boost::arg<1>, boost::arg<2> >::a3_)' (type 'int') to type 'int&' /usr/include/boost/bind/mem_fn_template.hpp:291:25: note: candidate: template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(const U&, A1, A2) const [with U = U; R = void; T = bar; A1 = const int&; A2 = int&] /usr/include/boost/bind/mem_fn_template.hpp:291:25: note: template argument deduction/substitution failed: /usr/include/boost/bind/bind.hpp:398:35: note: cannot convert '(& a)->boost::_bi::rrlist3<int, int, int>::operator[](boost::_bi::storage3<boost::_bi::value<bar*>, boost::arg<1>, boost::arg<2> >::a3_)' (type 'int') to type 'int&' /usr/include/boost/bind/mem_fn_template.hpp:299:7: note: candidate: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T&, A1, A2) const [with R = void; T = bar; A1 = const int&; A2 = int&] /usr/include/boost/bind/mem_fn_template.hpp:299:7: note: no known conversion for argument 1 from 'bar*' to 'bar&' 

If I try on another machine with Boost 1.55, it compiles just fine. (The project was also compiled on the same computer when Boost 1.55 is pointed to, so the problem does not seem to be a compiler.) So, apparently, something has changed in Boost, which recently caused an error.

I did not write this code, I am not familiar with the boost::function and boost::bind guts. If someone can explain to me why this breaks with the newer Boost, and either: a) how to fix it, or b) why this code is broken, it would be very grateful!

+5
source share
1 answer

The problem is that boost::function become more stringent in matching function signatures (I think it more closely matches the behavior of std::function ). Your function is declared as boost::function3< void, Arg1, Arg2, Arg3 > , however the function you are binding to accepts int const& and int& .

There are several ways to fix this. You could:

  • Change the instance foo foo<int, int> in bar to foo<int const&, int&> .
  • Change the declaration of function_t to boost::function3<void, Arg1, Arg2 const&, Arg3&> .
  • Change the signature of bar::func to accept its arguments by value.
+6
source

Source: https://habr.com/ru/post/1270648/


All Articles