boost::bind and <unresolved overloaded function type>
Thu 2008-01-31 23:45
I had a hard time Googling a solution to this particular woe. Alas the exact
string "unresolved overloaded function type" doesn't give anything useful
with "boost::bind" and "boost:mem_fn". This is the typical sort error
message from g++:
foo.cpp:18: error: no matching function for call to
'bind(<unresolved overloaded function type>,
const boost::reference_wrapper<FooMaster>, boost::arg<1> (&)())'
I've generated this using a rather contrived example based on the use pattern that was causing my woe:
#include <iostream>
#include <boost/bind.hpp>
class FooMaster {
public:
void foo(std::string &s) {
std::cout << "foo(s=" << s << ")" << std::endl;
}
void foo(int x) {
std::cout << "foo(x=" << x << ")" << std::endl;
}
};
int main(int argc, char **argv) {
FooMaster fm;
boost::bind(&FooMaster::foo, boost::ref(fm), _1)(10);
return 0;
}
The problem is obvious of course, it is exactly as the compiler is telling
you. Mr compiler has no idea which "foo" you're talking about. "But Mr
Compiler, it is obvious!" You say. "I'm not passing it a bloody string!"
Sometimes you just have to understand that Mr Compiler isn't you and needs a
little hand-holding.
The issue clearly boils down to FooMaster having two methods that match
&FooMaster::foo. This signature, used to instantiate the bind
template, doesn't take into account the arguments, so which foo are we
taling about?! Alas, as obvious as the problem was I didn't find the
solution so obvious. I just don't cut it as a C++ guy sometimes. I'd given
up on the problem in fact, but then I stumbled on a solution while looking into
some other problem I had. It was one of those "oh, duh!" moments really, I was
looking at some code that assigned a member function pointer. The type
specification for such a thing includes the argument types! So here's a
modified main that uses one extra step in order to explain what we want to
the compiler:
int main(int argc, char **argv) {
FooMaster fm;
// Create a variable of the desired function signature type and assign
// using desired member function. This will resolve the correct
// function thanks to the signature including the argument types.
void (FooMaster::*fn)(int) = &FooMaster::foo;
// Now pass the function variable to the template method so that it knows
// exactly which function we mean.
boost::bind(fn, boost::ref(fm), _1)(10);
return 0;
}
All you have to do is give Mr Compiler a little bit of a helping hand…
Joy!
Recent Entries
Categories
- Entries - 260
- Beer - 1
- Cycling - 2
- Food - 53
- Cooking - 26
- Hare - 5
- Soup - 1
- Eating - 5
- England - 5
- London - 4
- Rickmansworth - 1
- Produce - 14
- Ristretto - 8
- Health - 3
- Money - 2
- Random - 74
- Technology - 93
- Code - 22
- General - 46
- Security - 23
- Work - 2
- Wanderings - 32
- Australia - 2
- Barcelona - 2
- Belgium - 2
- England - 15
- Cambridge_Easter - 3
- Lakes - 9
- Finland - 4
- France - 1
- Germany - 1
- Ramble - 3
- Wales - 1




4 Responses
Best regards,
Rudi
The solution I have is sufficient for the problem I hit, I wasn't planning on making it more general! :)
I'm not quite sure of the scenario you're describing though. If you map a particular function with a funtion pointer it'll lock to exactly the function matching the signature (and there can't be multiple of these in a class.) So the method for binding above should still work, as in the following example (fingers crossed that my comment submission will handle this!):
-----------------------------------
#include <string>
#include <iostream>
#include <list>
#include <algorithm>
#include <boost/bind.hpp>
class Base
{
public:
Base(const std::string & str)
: m_str(str)
{};
virtual ~Base()
{};
const std::string & getStr() const
{ return m_str; }
private:
std::string m_str;
};
class DerivedOne : public Base
{
public:
DerivedOne().
: Base("DerivedOne")
{};
virtual ~DerivedOne()
{};
};
class DerivedTwo : public Base
{
public:
DerivedTwo().
: Base("DerivedTwo")
{};
virtual ~DerivedTwo()
{};
};
class Visitor
{
public:
void visit(const Base * inst)
{ std::cout << inst->getStr() << std::endl; }
void visit(const DerivedOne * inst)
{ std::cout << "Foo: " << inst->getStr() << std::endl; }
void visit(const std::string & str)
{ std::cout << str << std::endl; }
};
int main()
{
std::list<Base *> baseList;
baseList.push_back(new DerivedOne);
baseList.push_back(new DerivedTwo);
baseList.push_back(new DerivedTwo);
baseList.push_back(new DerivedOne);
Visitor visitor;
void (Visitor::fn)(const Base inst) = &Visitor::visit;
std::for_each(baseList.begin(), baseList.end(), boost::bind(fn, boost::ref(visitor), _1));
return 0;
}
-----------------------------------
This code compiles and runs on for me, with g++ 4.1.3. My guess is that you probably mean something different to what I think. :)
#include <string>
#include <iostream>
#include <list>
#include <algorithm>
#include <boost/bind.hpp>
class Visitor;
class Base
{
public:
Base(const std::string & str) : m_str(str)
{};
virtual ~Base()
{};
const std::string & getStr() const
{
return m_str;
}
virtual void accept( Visitor& v ) = 0;
private:
std::string m_str;
};
class DerivedOne : public Base
{
public:
DerivedOne() : Base("DerivedOne")
{};
virtual ~DerivedOne()
{};
void accept( Visitor& v );
};
class DerivedTwo : public Base
{
public:
DerivedTwo() : Base("DerivedTwo")
{};
virtual ~DerivedTwo()
{};
void accept( Visitor& v );
};
class Visitor
{
public:
void visit( Base * inst)
{
inst->accept( *this );
}
void visit(const DerivedOne * inst)
{
std::cout << "<1>Foo: " << inst->getStr() << std::endl;
}
void visit(const DerivedTwo * inst)
{
std::cout << "<2>Foo: " << inst->getStr() << std::endl;
}
};
void DerivedOne::accept( Visitor& v )
{
v.visit( this );
}
void DerivedTwo::accept( Visitor& v )
{
v.visit( this );
}
int main()
{
std::list<Base *> baseList;
baseList.push_back(new DerivedOne);
baseList.push_back(new DerivedTwo);
baseList.push_back(new DerivedTwo);
baseList.push_back(new DerivedOne);
Visitor visitor;
void (Visitor::*visit)(Base *inst) = &Visitor::visit;
std::for_each(baseList.begin(), baseList.end(), boost::bind(visit, boost::ref(visitor), _1));
return 0;
}
I compiled it with g++ 4.1.2!
Best regard,
Rudi.
What is "better"? Less code? Less indirection? (I.e. performance.)
I guess the issue could be performance... if this is part of very tight performance critical code then I think you'd want to reconsider the entire design :)
Another common approach to your problem, coming from C, is to create your own jump table (or switch statement) based on a type identifier. This isn't very C++y though, but it can help with performance. Similar would be some sort of registration and execution of a fn ptr, callback style.
Hrm, and templates aren't other going to help because you're after runtime evaluation.
I suppose you're probably looking for elegance? In which case C-style solutions aren't it :) I'd be interested to know if you do find a solution that meets your criteria for "better." (And what the criteria are as well, of course!)