Member function pointers to member functions with default arguments

Discussion in 'C++' started by Hamish, Jan 25, 2008.

  1. Hamish

    Hamish Guest

    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.
    Hamish, Jan 25, 2008
    #1
    1. Advertising

  2. * 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?
    Alf P. Steinbach, Jan 25, 2008
    #2
    1. Advertising

  3. Hamish

    Hamish Guest

    Re: Member function pointers to member functions with defaultarguments

    On Jan 25, 4:40 pm, "Alf P. Steinbach" <> 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.
    Hamish, Jan 25, 2008
    #3
  4. 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?
    Alf P. Steinbach, Jan 25, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    2
    Views:
    347
  2. tutmann
    Replies:
    4
    Views:
    425
  3. claudiu
    Replies:
    12
    Views:
    4,401
    Gianni Mariani
    Aug 6, 2007
  4. paul
    Replies:
    8
    Views:
    698
    Alf P. Steinbach
    Apr 30, 2009
  5. Hicham Mouline
    Replies:
    0
    Views:
    314
    Hicham Mouline
    Sep 15, 2009
Loading...

Share This Page