"no match for call" error using boost::bind - c++

I'm still new to boost::bind, and now porting a program that was written 2 yrs ago in 2009, seeing the compile error below. Any idea to workaround would be appreciated.
Extracted cpp file:
class ClassA {
private:
cNamespace::Bounds bounds_msg_;
void boundsHandler(const PublisherPtr& p) {
p->publish(bounds_msg_);
}
void funcA() {
node_->advertise<cNamespace::Bounds>("bounds", 10,
boost::bind(&ClassA::boundsHandler, this, _1)); // <---- Line 445
}
};
Error upon CMake:
/home/userA/ClassA.cpp:445: instantiated from here
/usr/include/boost/bind/bind.hpp:313: error: no match for call to ‘(boost::_mfi::mf1<void, ClassA, const PublisherPtr&>) (ClassA*&, const ros::SingleSubscriberPublisher&)’
Environment: Ubuntu 10.10, g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Might not be necessary but API reference of function advertise is here, or:
template<class M >
Publisher advertise (const std::string &topic,
uint32_t queue_size,
const SubscriberStatusCallback &connect_cb,
const SubscriberStatusCallback &disconnect_cb=SubscriberStatusCallback(),
const VoidConstPtr &tracked_object=VoidConstPtr(),
bool latch=false)

It looks like the function object that is produced by boost::bind is called with a different type than the function you bound.
i.e. it's called with const ros::SingleSubscriberPublisher& argument, instead of the expected const PublisherPtr& p.
Assuming SubscriberStatusCallback is a boost::function, you should make sure its argument matches the one you bound.

Related

Standard overloaded std::abs doesn't match std::function<double (double)>

I'm getting the following error
min.cpp:17:30: error: no viable conversion from '<overloaded function type>' to 'Container::UnaryFun' (aka 'function<double (double)>')
this->addFunction("abs", abs);
when trying to compile the following code:
#include <cmath>
#include <string>
#include <functional>
class Test
{
public:
using UnaryFun = std::function<double (double)>;
Test()
{
this->addFunction("abs", abs);
}
auto addFunction(const std::string& name, UnaryFun fun) -> void
{
// ...
}
};
auto main() -> int {
Test eval;
return 0;
}
I've tried to check the declaration of std::abs for argument double and return type double and looks like this:
inline _LIBCPP_INLINE_VISIBILITY double abs(double __lcpp_x) _NOEXCEPT {
return __builtin_fabs(__lcpp_x);
}
in /usr/local/Cellar/llvm/15.0.7_1/include/c++/v1/stdlib.h.
It is accesible specifically for the double type. I've checked this by adding:
double a = 5;
double b = std::abs(a);
and this compiles without problems or conversion warnings.
I've tried to declare my own abs function like so:
inline double xabs(double val)
{
return val < 0 ? -val : val;
}
and then change the following code like so to use this new xabs instead of std::abs
this->addFunction("abs", xabs);
and after this change, the code compiles.
Any ideas why the code with std::abs doesn't compile?
My environment:
OS: Mac OS 12.6
Compiler:
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Command to compile: g++ -std=c++2a -o min min.cpp
Update based on comments
I dug a bit deeper, and it seems that there is a problem with how std::function is declared, which led to the problem above.
If I declare addFunction like so, without std::function, the problem disappears.
auto addFunction(const std::string& name, double (*fun)(double)) -> void
{
}
This means that the compiler cannot figure out the matching abs if std::function is used but it can identify the matching overload if the type of the function is described directly without std::function.
The problem is that, since it has multiple overloads, std::abs doesn't have a single type. That means that the compiler can't select a std::function constructor to use to convert it since it can't deduce a type for the constructor's template parameter.
There are a couple of ways to get around that:
Use a cast:
addFunction("abs", std::static_cast<double(*)(double)>(std::abs));
Wrap it in a lambda:
addFunction("abs", [](double d) { return std::abs(d); });
As you've done, wrap it in a non-overloaded function

boost function bind compiled with a conversion error

I have the following code
#include <boost/function.hpp>
#include <boost/bind.hpp>
class Foo {
public:
int getIfoo();
};
int Foo::getIfoo() {
return 5;
}
int main () {
boost::function<int (Foo)> getIntFoo;
getIntFoo = boost::bind( &Foo::getIfoo, _1 );
return 0;
}
When I compile with the following command g++ TestBoostBind.cpp I've got the following error
/includes/boost_1_60_0/boost/bind/mem_fn_template.hpp:35:36: error: invalid conversion from ‘const Foo*’ to ‘Foo*’ [-fpermissive]
BOOST_MEM_FN_RETURN (u.*f_)();
~~~~~~~^~
I'm confused about the source of the error whether it's originally from my code or the boost library. Does anyone know what the error means and how to fix it? I use g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 and boost.1.60
When binding to a member function, the first argument needs to be a pointer or a reference to the object to call the function on. It specifically can't be a value (an actual object instance). The boost::bind function have special cases for these two alternatives to generate the correct objects. It does not have any special case for passing by value.
Therefore you need to define getIntFoo as a function taking a pointer to Foo:
boost::function<int (Foo*)> getIntFoo;
Or a reference:
boost::function<int (Foo&)> getIntFoo;
You could try to use std::mem_fn to achieve the same goal:
Foo f;
std::function<int(Foo &)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(f);
or if you need pointer argument, std::function could resolve this for you:
Foo f;
std::function<int(Foo *)> getIntFoo = std::mem_fn(&Foo::getIfoo);
int ret = getIntFoo(&f);
boost have its own alternative

bind shared_ptr::reset - no matching overloaded function found

the following code snippet worked in Visual Studio 2005 (with boost 1.34) but it fails to compile in Visual Studio 2015 (with boost 1.62) saying that "error C2672: 'boost::bind': no matching overloaded function found"
Am I missing something here?
Thank you!
typedef boost::shared_ptr< int > SProxySharedPtr;
SProxySharedPtr m_sptr_proxy;
auto a = boost::bind(&SProxySharedPtr::reset, &m_sptr_proxy);
boost::shared_ptr<.>::reset() is an overloaded member function. As a consequence, you have to designate explicitly which overload you want to use:
auto a = boost::bind(static_cast<void(SProxySharedPtr::*)()>(&SProxySharedPtr::reset), &m_sptr_proxy);
I tried to use GCC but saw similar errors. The only way I can get it compile is to subclass boost::shared_ptr as below (but maybe this is not what you are asking for):
typedef boost::shared_ptr<int> SProxySharedPtr;
struct Bar : SProxySharedPtr {
void reset() {
SProxySharedPtr::reset();
}
};
int main()
{
const Bar m_sptr_proxy;
boost::bind(&Bar::reset, &m_sptr_proxy);
}

GCC "no matching function for call.." errors

I am developing a cross platform code base where the initial work is done using MS VC2010 compiler.Later I compile it on Linux with GCC (4.7).In many cases I am receiving :
"No matching function for call .." error in GCC.I noticed that it complains mostly when method params are non constant references.For example this:
void MyClass::DoSomeWork(ObjectSP &sprt, const std::string someName, const std::string anotherName, const std::string path, int index) {
sprt->GetProp()->Update(path, false);
}
Once I change the method to this:
void MyClass::DoSomeWork(const ObjectSP& sprt, const std::string& someName, const std::string& anotherName, const std::string& path, int index) {
sprt->GetProp()->Update(path, false);
}
GCC stops complaining.
Why does it happen and why does it not happen in VC compilers?
It's illegal to bind a non-const reference to a temporary. Historically however VS compilers have been less strict about this.
So if you have a function with a non-const reference and you call it with a temporary object (e.g. the return value from a function), g++ will compain, but VS won't. In this case g++ is right.
Always prefer const references if you can.

c++ - error :invalid initialization of reference of type 'const testGetter*&' from expression of type 'testGetter* const'

I know it has come up a zillion times but this time it was autogenerated code :
class testGetter{
testGetter * ptr; // wrote this
public:
// this is autogenerated by eclipse
const testGetter*& getPtr() const {
return ptr;
}
void setPtr(const testGetter*& ptr) {
this->ptr = ptr;
}
};
I am on windows 7 mingw - g++ version 4.7.0
So is it a bug in the templates of eclipse (juno) ?
EDIT : compiler invocation :
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fpermissive -o Visitor.o "..\\Visitor.cpp"
EDIT 2013.06.12 : I should have added that I reported the thing after the feedback I got here
const testGetter*&
That represents a reference to a non-const pointer to a const testGetter. You cannot convert from a testGetter* to that type as that would break const-correctness in the following example:
const testGetter tmp;
testGetter t;
t.getPtr() = &tmp; // !!!
If the conversion was allowed the above code would compile, and after the line marked with the !!! the pointer stored inside t (which is of type testGetter*) would be pointing to a const testGetter, breaking const-correctness in the code.
You probably want to return just a pointer, not a reference to a pointer:
const testGetter* getPtr() const
Or alternatively add an extra const to guarantee const-correctness:
const testGetter *const& getPtr() const
In either case, the code is ensuring that you don't set the internal testGetter* to point to a const testGetter.
If the getter was autogenerated by the tool (Eclipse), then the tool has a bug or is a bit too simplistic to generate correct code. You will need to either create the getter manually or else fix the output of the generator.
Sidenote: Given a choice of Eclipse CDT or g++, I'd bet that the bug is in eclipse more often than not.