473,420 Members | 4,511 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,420 software developers and data experts.

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_cast<void (C::*)(char)>(C::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(char);
bind(static_cast<MemFun1Char>(C::F), &o, _1);

If we had these...:

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

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

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

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

TP2,

TP3)
{
return pFunc;
}

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

bind(resolve_cast1<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_cast2<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_cast1(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<char>(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 2702
"Arturo Cuebas" <acuebas@NO_SPAM.houston.rr.com> 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_cast<void (C::*)(char)>(C::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(char);
bind(static_cast<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_SPAM.houston.rr.com> 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_cast<void (C::*)(char)>(C::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(char);
bind(static_cast<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 "syntactically 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<char>(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<char>(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<void (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<char>(C::F)

than this:

static_cast<void (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_SPAM.houston.rr.com> wrote in message
news:1r********************************@4ax.com...
<snip>
I think it's easier to follow this:

resolve_cast1<char>(C::F)

than this:

static_cast<void (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_SPAM.houston.rr.com> 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_cast<void (C::*)(char)>(C::F), &o, _1);

And if you're a nice guy:

typedef void (C::* MemFun1Char)(char);
bind(static_cast<MemFun1Char>(C::F), &o, _1);

If we had these...:

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

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

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

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

TP2,

TP3)
{
return pFunc;
}

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

bind(resolve_cast1<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_cast2<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_cast1(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<char>(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
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. ...
0
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...
2
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?...
1
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:...
1
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 { ... };...
1
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>...
3
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...
0
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...
1
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...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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...
0
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...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
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...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

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.