Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Member function pointers to member functions with default arguments (http://www.velocityreviews.com/forums/t587114-member-function-pointers-to-member-functions-with-default-arguments.html)

Hamish 01-25-2008 05:26 AM

Member function pointers to member functions with default arguments
 
Hi,

The following doesn't compile (using g++ 4.0.3 with all warnings, -
pedantic, -ansi, etc.):

class X {
public:
int f(int i = 0) { return i; }
};

int main() {
int (X::*blah)() = &X::f; // Invalid conversion.
X x;
return (x.*blah)();
}

I always thought that specifying default arguments (like above) was a
kind of shorthand for something like:

class X {
public:
int f(int i) { return i; }
int f() { return f(0); }
};

int main() {
int (X::*blah)() = &X::f; // Okay now.
X x;
return (x.*blah)();
}

Is there a way to get the behaviour of the second code snippet while
using default arguments like in the first code snippet?

Cheers,
Hamish.

Alf P. Steinbach 01-25-2008 05:40 AM

Re: Member function pointers to member functions with default arguments
 
* Hamish:
>
> The following doesn't compile (using g++ 4.0.3 with all warnings, -
> pedantic, -ansi, etc.):
>
> class X {
> public:
> int f(int i = 0) { return i; }
> };
>
> int main() {
> int (X::*blah)() = &X::f; // Invalid conversion.
> X x;
> return (x.*blah)();
> }
>
> I always thought that specifying default arguments (like above) was a
> kind of shorthand for something like:
>
> class X {
> public:
> int f(int i) { return i; }
> int f() { return f(0); }
> };
>
> int main() {
> int (X::*blah)() = &X::f; // Okay now.
> X x;
> return (x.*blah)();
> }


No, it's not.

A default argument is an argument that's present, it's just filled in by
the compiler in each particular call that doesn't specify it.


> Is there a way to get the behaviour of the second code snippet while
> using default arguments like in the first code snippet?


Depends what you're trying to achieve.

In general member function pointers are often (to the degree they're
used at all) abused to emulate the effect one would get with a virtual
function.

If a virtual function doesn't serve your needs, although unlikely, you
can always just introduce an overload of f in class X.


Cheers, & hth.,

- Alf


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Hamish 01-25-2008 06:09 AM

Re: Member function pointers to member functions with defaultarguments
 
On Jan 25, 4:40 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * Hamish:
>
>
>
>
>
> > The following doesn't compile (using g++ 4.0.3 with all warnings, -
> > pedantic, -ansi, etc.):

>
> > class X {
> > public:
> > int f(int i = 0) { return i; }
> > };

>
> > int main() {
> > int (X::*blah)() = &X::f; // Invalid conversion.
> > X x;
> > return (x.*blah)();
> > }

>
> > I always thought that specifying default arguments (like above) was a
> > kind of shorthand for something like:

>
> > class X {
> > public:
> > int f(int i) { return i; }
> > int f() { return f(0); }
> > };

>
> > int main() {
> > int (X::*blah)() = &X::f; // Okay now.
> > X x;
> > return (x.*blah)();
> > }

>
> No, it's not.


Indeed.

> A default argument is an argument that's present, it's just filled in by
> the compiler in each particular call that doesn't specify it.


I thought that might be the case, which made me thing that perhaps
there was syntax for declaring a member function pointer that has
default arguments, but nothing I tried worked. Probably for the best,
as the syntax for member function pointers is probably opaque enough
as it is.

> > Is there a way to get the behaviour of the second code snippet while
> > using default arguments like in the first code snippet?

>
> Depends what you're trying to achieve.
>
> In general member function pointers are often (to the degree they're
> used at all) abused to emulate the effect one would get with a virtual
> function.
>
> If a virtual function doesn't serve your needs, although unlikely, you
> can always just introduce an overload of f in class X.


Neither of those solutions are possible, as the member functions I'm
using are from a library not under the control of my development
team. I solved the problem by templatising the function that takes
the member function pointer:

#include <iostream>
using namespace std;

class X {
public:
void f(int i = 0) { cout << "i = " << i << endl; }
};

template< typename Fn >
void func(Fn f, X &x) {
(x.*f)();
}

int main() {
X x;
func(&X::f, x);
return 0;
}
// Prints: i = 0.

I was a bit surprised it worked, to be honest. As you said, &X::f
has type void (X::*)(int) so I would have thought Fn would resolve
as void (X::*)(int) causing a compile error on the line (x.*f)();.
Oh well, I'm not complaining.

Hamish.

Alf P. Steinbach 01-25-2008 06:46 AM

Re: Member function pointers to member functions with default arguments
 
* Hamish -> Alf P. Steinbach:
>
> #include <iostream>
> using namespace std;
>
> class X {
> public:
> void f(int i = 0) { cout << "i = " << i << endl; }
> };
>
> template< typename Fn >
> void func(Fn f, X &x) {
> (x.*f)();
> }
>
> int main() {
> X x;
> func(&X::f, x);
> return 0;
> }
> // Prints: i = 0.
>
> I was a bit surprised it worked, to be honest. As you said, &X::f
> has type void (X::*)(int) so I would have thought Fn would resolve
> as void (X::*)(int) causing a compile error on the line (x.*f)();.
> Oh well, I'm not complaining.


You should be. :-)


<comeau>
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 11: error: too few arguments in function call
(x.*f)();
^
detected during instantiation of
"void func(Fn, X &) [with Fn=void (X::*)(int)]" at
line 16

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed
Hit the Back Button to review your code and compile options.
Compiled with C++0x extensions enabled.
</comeau>


<msvc>
vc_project.cpp(11) : error C2198: 'void (__thiscall X::* )(int)' : too
few arguments for call through pointer-to-functio
n
vc_project.cpp(16) : see reference to function template
instantiation 'void func<void(__thiscall X::* )(int)>(Fn
,X &)' being compiled
with
[
Fn=void (__thiscall X::* )(int)
]
</msvc>


<g++>
<url: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=4205>
</g++>



Cheers, & hth.,

- Alf


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


All times are GMT. The time now is 05:28 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.