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

F

Firstname Lastname

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

Martijn Mulder

Firstname said:
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
 
M

Martijn Mulder

Martijn said:
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.
 
S

Siemel Naran

Martijn Mulder said:
Firstname Lastname wrote:
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.
 

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,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top