I was trying to compile a project that was written against Boost 1.55 against newer Boost 1.63, and I am running into a really strange error related to bind
/function
. Here's the 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 select snippets of the errors I'm getting:
/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 that has Boost 1.55, it compiles just fine. (The project also compiled okay on the same machine when pointed to a build of Boost 1.55, so the problem does not seem to be the compiler.) So, apparently something has changed in Boost that is newly causing this to fail.
I didn't write this code, not am I intimately familiar with the guts of boost::function
and boost::bind
. If someone could explain to me why this is breaking with newer Boost, and either a) how to fix it, or b) why the above code is broken, it would be much appreciated!
The problem is that boost::function
has become stricter in matching the function signature (I think to more closely match the behavior of std::function
). Your function is declared to be boost::function3< void, Arg1, Arg2, Arg3 >
, however, the function you're binding to it takes int const&
and int&
.
There are a couple of ways to fix this. You could:
foo<int, int>
in bar
to be foo<int const&, int&>
.function_t
to be boost::function3<void, Arg1, Arg2 const&, Arg3&>
.bar::func
to accept its arguments by value.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With