Cannot match void (T::* ptr)() when base class of T defines function

Discussion in 'C++' started by Firstname Lastname, Feb 25, 2005.

  1. In a function call, for example function(Class(), &Class::memfunc), my
    compiler cannot match the 2nd argument when: (1) Class is a template
    parameter, and (2) the base class of Class defines memfunc but Class itself
    does not.

    Is this the correct behavior? Second, are there any workarounds?


    Consider the following program, which has a compile error in the last line
    silly(b, &B::f).


    #include <iostream>
    #include <typeinfo>

    using std::cout;


    struct A
    {
    A() { }
    void f() const { cout << "A::f()\n"; }
    };

    struct B : A
    {
    };

    template <class T>
    void silly(const T& t, void (T::* ptr)() const)
    {
    (t.*ptr)();
    }

    int main(int argc, char const *const * argv, char const *const * env)
    {
    const A a;
    silly(a, &A::f);

    const B b;
    silly(b, &B::f); // compile error: can't match silly(const B&, void
    (A::*)())
    }



    If we replace the

    template <class T>
    void silly(const T& t, void (T::* ptr)() const)

    with

    void silly(const B& t, void (B::* ptr)() const)

    then the last line compiles fine.
     
    Firstname Lastname, Feb 25, 2005
    #1
    1. Advertising

  2. Firstname Lastname wrote:
    > In a function call, for example function(Class(),
    > &Class::memfunc), my compiler cannot match the 2nd
    > argument when: (1) Class is a template parameter, and (2)
    > the base class of Class defines memfunc but Class itself
    > does not.
    >
    > Is this the correct behavior? Second, are there any
    > workarounds?
    >
    >
    > Consider the following program, which has a compile error
    > in the last line silly(b, &B::f).
    >
    >
    > #include <iostream>
    > #include <typeinfo>
    >
    > using std::cout;
    >
    >
    > struct A
    > {
    > A() { }
    > void f() const { cout << "A::f()\n"; }
    > };
    >
    > struct B : A
    > {
    > };
    >
    > template <class T>
    > void silly(const T& t, void (T::* ptr)() const)
    > {
    > (t.*ptr)();
    > }
    >
    > int main(int argc, char const *const * argv, char const
    > *const * env) {
    > const A a;
    > silly(a, &A::f);
    >
    > const B b;
    > silly(b, &B::f); // compile error: can't match
    > silly(const B&, void (A::*)())
    > }
    >
    >
    >
    > If we replace the
    >
    > template <class T>
    > void silly(const T& t, void (T::* ptr)() const)
    >
    > with
    >
    > void silly(const B& t, void (B::* ptr)() const)
    >
    > then the last line compiles fine.




    When you replace the last call to silly() in main to

    silly((A)b, &B::f); // cast b to type A

    your code does compile. Silly and useless
     
    Martijn Mulder, Feb 25, 2005
    #2
    1. Advertising

  3. Martijn Mulder wrote:
    > Firstname Lastname wrote:
    >> In a function call, for example function(Class(),
    >> &Class::memfunc), my compiler cannot match the 2nd
    >> argument when: (1) Class is a template parameter, and (2)
    >> the base class of Class defines memfunc but Class itself
    >> does not.
    >>
    >> Is this the correct behavior? Second, are there any
    >> workarounds?
    >>
    >>
    >> Consider the following program, which has a compile error
    >> in the last line silly(b, &B::f).
    >>
    >>
    >> #include <iostream>
    >> #include <typeinfo>
    >>
    >> using std::cout;
    >>
    >>
    >> struct A
    >> {
    >> A() { }
    >> void f() const { cout << "A::f()\n"; }
    >> };
    >>
    >> struct B : A
    >> {
    >> };
    >>
    >> template <class T>
    >> void silly(const T& t, void (T::* ptr)() const)
    >> {
    >> (t.*ptr)();
    >> }
    >>
    >> int main(int argc, char const *const * argv, char const
    >> *const * env) {
    >> const A a;
    >> silly(a, &A::f);
    >>
    >> const B b;
    >> silly(b, &B::f); // compile error: can't match
    >> silly(const B&, void (A::*)())
    >> }
    >>
    >>
    >>
    >> If we replace the
    >>
    >> template <class T>
    >> void silly(const T& t, void (T::* ptr)() const)
    >>
    >> with
    >>
    >> void silly(const B& t, void (B::* ptr)() const)
    >>
    >> then the last line compiles fine.

    >
    >
    >
    > When you replace the last call to silly() in main to
    >
    > silly((A)b, &B::f); // cast b to type A
    >
    > your code does compile. Silly and useless



    On second thought, silly, yes, but not useless. It's a _reference_, so virtual
    function invoked on the object will behave correctly.
     
    Martijn Mulder, Feb 25, 2005
    #3
  4. Firstname Lastname

    Siemel Naran Guest

    "Martijn Mulder" <i@m> wrote in message news:421f24a8$0$51221
    > Firstname Lastname wrote:


    > > #include <iostream>
    > > #include <typeinfo>
    > >
    > > using std::cout;
    > >
    > >
    > > struct A
    > > {
    > > A() { }
    > > void f() const { cout << "A::f()\n"; }
    > > };
    > >
    > > struct B : A
    > > {
    > > };
    > >
    > > template <class T>
    > > void silly(const T& t, void (T::* ptr)() const)
    > > {
    > > (t.*ptr)();
    > > }
    > >
    > > int main(int argc, char const *const * argv, char const
    > > *const * env) {
    > > const A a;
    > > silly(a, &A::f);
    > >
    > > const B b;
    > > silly(b, &B::f); // compile error: can't match
    > > }


    > When you replace the last call to silly() in main to
    >
    > silly((A)b, &B::f); // cast b to type A
    >
    > your code does compile. Silly and useless


    OK. But is this slicing (meaning the B only part gets sliced away because
    we're converting a B object to an A object)? In my real example function
    f() is indeed not virtual, but it calls a protected virtual function, and
    furthermore class A is abstract. Thinking along your line, I suppose one
    could use static cast

    silly(static_cast<const A&>(b), &A::f);

    Would this work? No time yet to compile it, will try later.
     
    Siemel Naran, Feb 26, 2005
    #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. Ollej Reemt
    Replies:
    7
    Views:
    543
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    791
    The Real OS/2 Guy
    Oct 28, 2003
  3. theotyflos
    Replies:
    3
    Views:
    474
    Thomas Matthews
    Feb 19, 2004
  4. Replies:
    10
    Views:
    525
    James Kanze
    Sep 23, 2007
  5. DSF
    Replies:
    7
    Views:
    108
    James Kuyper
    Jun 12, 2014
Loading...

Share This Page