473,573 Members | 3,075 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Overload resolution & boost::bind

The program below contains a compile error. Following the program you
will find the typical fix then my idea for a library that facilitates
a more elegant fix.

#include <boost\bind.hpp >

using namespace boost;

struct C
{
void F(char, char){}
void F(int, int){}
void F(char, int){}
void F(char){}
};

int main()
{
C o;
bind(
C::F, // error: which C::F?
&o,
_1
);
}

Typical solution:

bind(static_cas t<void (C::*)(char)>(C ::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(ch ar);
bind(static_cas t<MemFun1Char>( C::F), &o, _1);

If we had these...:

template<typena me TC, typename TR>
TR (TC::* resolve_cast0(T R (TC::* pFunc)(void)))( void)
{
return pFunc;
}

template<typena me TP, typename TC, typename TR>
TR (TC::* resolve_cast1(T R (TC::* pFunc)(TP)))(TP )
{
return pFunc;
}

template<typena me TP1, typename TP2, typename TC, typename TR>
TR (TC::* resolve_cast2(T R (TC::* pFunc)(TP1, TP2)))(TP1, TP2)
{
return pFunc;
}

template<typena me TP1,
typename TP2,
typename TP3,
typename TC,
typename TR>
TR (TC::* resolve_cast3(T R (TC::* pFunc)(TP1, TP2, TP3)))(TP1,

TP2,

TP3)
{
return pFunc;
}

....etc; the bind call would look like this:

bind(resolve_ca st1<char>(C::F) , &o, _1);

Benefits:
1.) No ugly syntax due to specifying member function pointer type with
static_cast.
or
2.) One less line of code due to no typedef.

Another example; if I want to specify C::F(char, int):

bind(resolve_ca st2<char, int>(C::F), &o, _1, _2);

Now, if we had this...:

struct D
{
void F(char, char){}
void F(char){}
};

....things would be even nicer:

If I want to call D::F(char, char):

bind(
resolve_cast2(D ::F), //notice no template params specified.
&o,
_1,
_2);

If I want to call D::F(char):

bind(resolve_ca st1(D::F), &o, _1);

It would be nice to do this, but I can't find a way:

If I want to call C::F(char):

bind(
resolve_cast<ch ar>(C::F), // notice no number appended
&o,
_1);

If I want to call D::F(char, char):

bind(
resolve_cast<2> (D::F), // notice no number appended
&o,
_1);
Has anyone seen this before?
Do you think this is worth having in a library?
Is it possible to implement a form without a number appended?
Is there a name better than resolve_cast?

This was tested only in VC7.1.
Jul 22 '05 #1
4 2718
"Arturo Cuebas" <acuebas@NO_SPA M.houston.rr.co m> wrote in message
news:8c******** *************** *********@4ax.c om...
The program below contains a compile error. Following the program you
will find the typical fix then my idea for a library that facilitates
a more elegant fix.

#include <boost\bind.hpp >

using namespace boost;

struct C
{
void F(char, char){}
void F(int, int){}
void F(char, int){}
void F(char){}
};

int main()
{
C o;
bind(
C::F, // error: which C::F?
&o,
_1
);
}

Typical solution:

bind(static_cas t<void (C::*)(char)>(C ::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(ch ar);
bind(static_cas t<MemFun1Char>( C::F), &o, _1);

[snipped solution involving templates]

While I admit that function pointer syntax can be ugly, the solution that
you proposed is unnecessary. IMHO, elegance is not measured in terms of
casts or punctuation symbols. While your proposed solution does eliminate
the function signature from the caller's code, it makes the caller's code
harder to follow. The proposed solution makes it harder to determine which
function is being called because the resolution is hidden by a template
function. Also, the solution does not eliminate the author's need to figure
out which function he/she needs to call, so it doesn't make anything easier
for him/her. In the end, the cure is worse than the disease.

--
David Hilsee
Jul 22 '05 #2
On Sat, 14 Aug 2004 01:31:19 -0400, "David Hilsee"
<da************ *@yahoo.com> wrote:
"Arturo Cuebas" <acuebas@NO_SPA M.houston.rr.co m> wrote in message
news:8c******* *************** **********@4ax. com...
The program below contains a compile error. Following the program you
will find the typical fix then my idea for a library that facilitates
a more elegant fix.

#include <boost\bind.hpp >

using namespace boost;

struct C
{
void F(char, char){}
void F(int, int){}
void F(char, int){}
void F(char){}
};

int main()
{
C o;
bind(
C::F, // error: which C::F?
&o,
_1
);
}

Typical solution:

bind(static_cas t<void (C::*)(char)>(C ::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(ch ar);
bind(static_cas t<MemFun1Char>( C::F), &o, _1);[snipped solution involving templates]

While I admit that function pointer syntax can be ugly, the solution that
you proposed is unnecessary. IMHO, elegance is not measured in terms of
casts or punctuation symbols.


I misused the word "elegant". Maybe "syntactica lly prettier" would
have been more appropriate.
While your proposed solution does eliminate
the function signature from the caller's code, it makes the caller's code
harder to follow. The proposed solution makes it harder to determine which
function is being called because the resolution is hidden by a template
function.
You have to explicitly specify the parameter types of the function you
want the template to resolve the overload to. This explicit
specification of the parameter types puts which function you want
called right in your face.

Consider:

resolve_cast1<c har>(C::F)

- The number indicates how many parameters the function you want
called takes (incidentally, I don't like this, I wish I could have
done resolve_cast<1, char>(C::F) or even resolve_cast<ch ar>(C::F), but
I couldn't figure it out).

- The template parameter(s) indicate what the parameter types are of
the function you want to call.

These two aspects make it clear as day which function you want to
call: The overload of F that takes 1 parameter of type char.

Now, consider:

static_cast<voi d (C::*)(char)>(C ::F)

Read from left to right (disregarding the parens and angle brackets):

"void" - The return type of the overloaded function - just because
it's part of the type you're casting to it has to be specified.

"C" - The class the function belongs to. Again, just because it's part
of the type you're casting to it has to be specified. Also, this is
redundant, as it is already specified in the "parameter" to
static_cast.

"::*" - Would you mind if all I said about this is "ugh"?

char - Now we've finally got to the part that truly differentiates the
function we want from the rest of the functions.

The parameter types are the only differences between functions that
allow the functions to be overloaded therefore it makes a certain
sense that that is the only thing the coder should have to specify -
and with this facility, that's all the coder has to.
Also, the solution does not eliminate the author's need to figure
out which function he/she needs to call,
psycic_resolve_ cast<>?
so it doesn't make anything easier for him/her.
I think it's easier to follow this:

resolve_cast1<c har>(C::F)

than this:

static_cast<voi d (C::*)(char)>(C ::F)

but that's just me. Maybe it just takes a little familiarity with what
resolve_cast1<> does, just like it takes a little familiarity with
lexical_cast<> and numeric_cast<> to know what they do.
In the end, the cure is worse than the disease.


Jul 22 '05 #3
"Arturo Cuebas" <acuebas@NO_SPA M.houston.rr.co m> wrote in message
news:1r******** *************** *********@4ax.c om...
<snip>
I think it's easier to follow this:

resolve_cast1<c har>(C::F)

than this:

static_cast<voi d (C::*)(char)>(C ::F)

but that's just me. Maybe it just takes a little familiarity with what
resolve_cast1<> does, just like it takes a little familiarity with
lexical_cast<> and numeric_cast<> to know what they do.


By the way, I believe you're missing the ampersands in your code (&C::F).

Keep in mind that it doesn't "do" anything. The other two actually provide
some functionality (conversion and range checking). The resolve_cast1
function template just provides an alternate syntax for specifying which
overload should be used. If you like it, that's fine, but I'm not
impressed. Function pointer syntax doesn't disgust me to the point where I
feel like it must be hidden behind template code, and the tiny bit of
redundancy doesn't bother me, either. Don't take it personally. I
generally object to additional code that is merely for aesthetics and has
little to no technical benefit.

--
David Hilsee
Jul 22 '05 #4
Arturo,

You might want to repost this on the boost mailing lists. You may get some
insights from the authors.

Jeff F

"Arturo Cuebas" <acuebas@NO_SPA M.houston.rr.co m> wrote in message
news:8c******** *************** *********@4ax.c om...
The program below contains a compile error. Following the program you
will find the typical fix then my idea for a library that facilitates
a more elegant fix.

#include <boost\bind.hpp >

using namespace boost;

struct C
{
void F(char, char){}
void F(int, int){}
void F(char, int){}
void F(char){}
};

int main()
{
C o;
bind(
C::F, // error: which C::F?
&o,
_1
);
}

Typical solution:

bind(static_cas t<void (C::*)(char)>(C ::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(ch ar);
bind(static_cas t<MemFun1Char>( C::F), &o, _1);

If we had these...:

template<typena me TC, typename TR>
TR (TC::* resolve_cast0(T R (TC::* pFunc)(void)))( void)
{
return pFunc;
}

template<typena me TP, typename TC, typename TR>
TR (TC::* resolve_cast1(T R (TC::* pFunc)(TP)))(TP )
{
return pFunc;
}

template<typena me TP1, typename TP2, typename TC, typename TR>
TR (TC::* resolve_cast2(T R (TC::* pFunc)(TP1, TP2)))(TP1, TP2)
{
return pFunc;
}

template<typena me TP1,
typename TP2,
typename TP3,
typename TC,
typename TR>
TR (TC::* resolve_cast3(T R (TC::* pFunc)(TP1, TP2, TP3)))(TP1,

TP2,

TP3)
{
return pFunc;
}

...etc; the bind call would look like this:

bind(resolve_ca st1<char>(C::F) , &o, _1);

Benefits:
1.) No ugly syntax due to specifying member function pointer type with
static_cast.
or
2.) One less line of code due to no typedef.

Another example; if I want to specify C::F(char, int):

bind(resolve_ca st2<char, int>(C::F), &o, _1, _2);

Now, if we had this...:

struct D
{
void F(char, char){}
void F(char){}
};

...things would be even nicer:

If I want to call D::F(char, char):

bind(
resolve_cast2(D ::F), //notice no template params specified.
&o,
_1,
_2);

If I want to call D::F(char):

bind(resolve_ca st1(D::F), &o, _1);

It would be nice to do this, but I can't find a way:

If I want to call C::F(char):

bind(
resolve_cast<ch ar>(C::F), // notice no number appended
&o,
_1);

If I want to call D::F(char, char):

bind(
resolve_cast<2> (D::F), // notice no number appended
&o,
_1);
Has anyone seen this before?
Do you think this is worth having in a library?
Is it possible to implement a form without a number appended?
Is there a name better than resolve_cast?

This was tested only in VC7.1.

Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2918
by: P G | last post by:
I hope this is on topic here. I have a problem compiling a simple example of the use of boost::bind. Please take a look at the program below. /**************************************************************************/ #include <boost/function.hpp> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp>
0
1022
by: Russell Hind | last post by:
Is it possible to create a boost::bind object for a managed class method? With non-managed classes, I can do boost::function<void ()> f = boost::bind(&Class_c::Function, this); Is there a way to do this for __gc classes? I do want to be able to assign the result to a boost::function, but can write my own wrapper if necessary. Thanks
2
2260
by: IndyStef | last post by:
I am trying to use boost's bind on a member function, on the VC8 compiler. After using several different attempts, I could not get it to work. Does anybody know what is wrong with the code below? The function that doesn't compile is foo::DoTheStuff. All three variations of the for-each loop won't build.
1
3602
by: yinglcs | last post by:
I have a function in STL which add the 'area' attribute of a list of Rect. template< class T1, class T2> class add_area_per_cent : public binary_function<T2, T1, T2> { public: add_area_per_cent() { }
1
3836
by: Olaf Petzold | last post by:
Hi, at this time I try to combine Qt and boost. Unfortunately I've run into trouble: void QWidget::insertAction ( QAction * before, QAction * action ); class QAction : public QWidget { ... }; class ActionCategory { ...
1
2788
by: Tigera | last post by:
Greetings, I am trying to learn to use the Boost library, and I've run into a frustrating problem with the line marked here: #include <boost/function.hpp> #include <boost/functional.hpp> #include <boost/bind.hpp> #include <iostream>
3
6800
by: =?iso-8859-1?B?Tm9yZGz2dw==?= | last post by:
Hey there, C++ Coders! I am learning multi-threading with boost and have come up with the following code example shown below. This example implements a test of the producer-consumer design pattern. gcc-4.1.2 however complains with errors about my use of boost::bind(). Doesn't bind support this way of specifying a function and its...
0
1185
by: joe | last post by:
I expected I could construct code like the following: return *(std::min_element(vec.begin(), vec.end(), bind(less<double>(), bind(&entry::foo, _1), bind(&entry::foo, _2)))); But if vec is only size 1, this returns '0'. min_element should work on size one vectors. If I add the guard "if(vec.size() == 1) { return *(vec.begin()); } "
1
1584
by: kittymaguire | last post by:
I am using VC2005 and have refined new to be new (_NORMAL_BLOCK ,__FILE__, __LINE__) for the debug build so that the location of memory leaks are reported. The problem that I have is when, I try to bind a functor using boost::bind boost::bind(&BoostWorkerThread::Stop, this) I get an syntax error in function_template.hpp '('
0
7776
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7686
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8014
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8200
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
8060
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5581
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3730
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
1297
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1038
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.