Compiler: g++ 4.4.3 Boost...: 1.49.0 OS......: Ubuntu
Note: It's been 15 years since I seriously used C++, so I'm relearning and learning new things as I also try to learn Boost.
Given the following code:
1. class Beta {
2. public:
3. std::string name();
4. }
5.
6. class Alpha {
7. public:
8. Beta m_beta;
9. }
10.
11. Alpha one;
For various reasons, I wanted to use boost:bind to achieve the same result as if "one.m_beta.name()" were called. I thought the following would do it:
12. boost::function<std::string(Alpha)>
13. b = boost::bind(
14. &Beta::name,
15. boost::bind(&Alpha::m_beta, _1)
16. );
17. cout << "NAME = " << b(one) << "\n";
But when I compile (g++ 4.4.3 on Ubuntu) I get the following error:
error: invalid conversion from ‘const Beta*’ to ‘Beta*’
After looking at the actual type definition resulting from lines 13-16, it looks like line 15 is becoming 'const Beta*', but the bind wrapping it expects 'Beta*'.
However, this DOES work:
30. boost::function<std::string(Beta)>
31. p1 = boost::bind(&Beta::name,_1);
32. boost::function<Beta(Alpha)>
33. p2 = boost::bind(&Alpha::m_beta,_1);
34. std::cout << "NAME = " << p1(p2(one)) << "\n";
But I really don't want to carry around a lot of intermediate variables. It did make me think that there must be some way to get the first version to work as well. I've already tried the following as replacements for line 15, but they all give out one or another error at compilation time too.
50. (boost::function<Beta&(Alpha)>)(boost::bind(&Alpha::m_beta,_1))
51. (boost::function<Beta(Alpha)>)(boost::bind(&Alpha::m_beta,_1))
52. (boost::function<Beta*(Alpha)>)(boost::bind(&Alpha::m_beta,_1))
53. boost::protect(boost::bind(&Alpha::m_beta,_1))
54. boost::ref(boost::bind(&Alpha::m_beta,_1))
55. const_cast<Beta*>(boost::bind(&Alpha::m_beta,_1))
56. const_cast<boost::function<Beta(Alpha) > >(boost::bind(&Alpha::m_beta,_1))
57. const_cast<boost::function<Beta*(Alpha) > >(boost::bind(&Alpha::m_beta,_1))
What am I missing?
Explicitly specify a Beta&
return type for the nested boost::bind
:
boost::function< std::string( Alpha ) > b =
boost::bind(
&Beta::name,
boost::bind< Beta& >( &Alpha::m_beta, _1 ) );
The reason the const Beta*
and Beta*
conversion errors are occurring is the result of boost::bind
having the same behavior as boost::mem_fn
, which states:
mem_fn
also supports pointers to data members by treating them as functions taking no arguments and returning a (const) reference to the member.`
Thus, the nested-bind is returning a const Beta&
, which is an invalid instance to invoke the non-const name()
member function on Beta
.