Member function pointers to member functions with default arguments

H

Hamish

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.
 
A

Alf P. Steinbach

* 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
 
H

Hamish

* Hamish:











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.
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.
 
A

Alf P. Steinbach

* 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top