From: Boris Bralo on
Hi all;

Here's the code that doesn't compile on latest Comeau (online) and GCC
4.4.0. It works with VC++ 2005 :

template <typename T>
class A{
public:
template <typename R>
void meth( T* o, R (T::*memfn)() ){
o->memfn();
}
};

struct AA{
int aaa(){ return 1; };
};

struct BB: public AA{
};

int main(int , char**){
BB bb;
A<BB> a;
a.meth(&bb, &BB::aaa);
return 0;
}

Both GCC and Comeau try to instantiate A::meth(&bb, &AA::aaa) and
report error. Are they right?

---
Boris


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: litb on
On 5 Mai, 03:35, Boris Bralo <boris.br...(a)gmail.com> wrote:
> Hi all;
>
> Here's the code that doesn't compile on latest Comeau (online) and GCC
> 4.4.0. It works with VC++ 2005 :
>
> template <typename T>
> class A{
> public:
> template <typename R>
> void meth( T* o, R (T::*memfn)() ){
> o->memfn();
>
> }
> };
>
> struct AA{
> int aaa(){ return 1; };
>
> };
>
> struct BB: public AA{
>
> };
>
> int main(int , char**){
> BB bb;
> A<BB> a;
> a.meth(&bb, &BB::aaa);
> return 0;
>
> }
>

comeau and gcc are right: &BB::aaa has type "int (AA::*)()" which is
not compatible with the type in the parameter during deduction which
has type "R (BB::*)()" even tho when assigned directly (if you call
"a.meth<int>(&bb, &BB::aaa)") it will work, during deduction such a
difference between the two types is not bridged, and you get a
deduction failure.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Yechezkel Mett on
On May 5, 4:35 am, Boris Bralo <boris.br...(a)gmail.com> wrote:
> Hi all;
>
> Here's the code that doesn't compile on latest Comeau (online) and GCC
> 4.4.0. It works with VC++ 2005 :
>

Simplified code demonstrating the issue:

struct AA{
int aaa(){ return 1; };
};

struct BB: public AA {};

template <typename R>
void f( BB* o, R (BB::*memfn)() ){
(o->*memfn)();
}

int main(int , char**){
BB bb;
f(&bb, &BB::aaa);
return 0;
}

>
> Both GCC and Comeau try to instantiate A::meth(&bb, &AA::aaa) and
> report error. Are they right?

I believe so. &BB::aaa is &AA::aaa and has the type int(AA::*)().
There is an implicit conversion from int(AA::*)() to int(BB::*)(), but
the parameter memfn is deduced (because the R is a template parameter)
and therefore does not undergo conversions.

The simplest solution seems to be to use a template parameter:

template <typename R, class T>
void f( BB* o, R (T::*memfn)() ){
(o->*memfn)();
}

Yechezkel Mett


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: red floyd on
On May 4, 6:35 pm, Boris Bralo <boris.br...(a)gmail.com> wrote:
> Hi all;
>
> Here's the code that doesn't compile on latest Comeau (online) and GCC
> 4.4.0. It works with VC++ 2005 :
>
> template <typename T>
> class A{
> public:
> template <typename R>
> void meth( T* o, R (T::*memfn)() ){
> o->memfn();

Shouldn't this be (o->*memfn)() ??


>
> }
> };


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Paul Bibbings on
Boris Bralo <boris.bralo(a)gmail.com> writes:

> Hi all;
>
> Here's the code that doesn't compile on latest Comeau (online) and GCC
> 4.4.0. It works with VC++ 2005 :

I very much doubt that it does work, as is, with VC++ 2005

> template <typename T>
> class A{
> public:
> template <typename R>
> void meth( T* o, R (T::*memfn)() ){
> o->memfn();

This is not the correct calling syntax on a pointer to member function,
and I am confident that VC++ 2005 would not accept this. It should be:

(o->*memfn)()

It's then worth noting that VC9 (VC++ 2008) is happy, given this
correction, with your code also.

> }
> };
>
> struct AA{
> int aaa(){ return 1; };
> };
>
> struct BB: public AA{
> };
>
> int main(int , char**){
> BB bb;
> A<BB> a;
> a.meth(&bb, &BB::aaa);
> return 0;
> }
>
> Both GCC and Comeau try to instantiate A::meth(&bb, &AA::aaa) and
> report error. Are they right?

I don't have immediate access to a copy of the Standard in order to be
able to locate a suitable reference to decide which implementation is
correct. However, it has always been the case as I've found it that,
where Comeau and VC disagree, ultimately Comeau turns out to be the more
correct. Note that, all three compilers (VC, Comeau, GCC) appear happy
with the change: template <typename R, typename U>
void meth( T* o, R (U::*memfn)() ){
(o->*memfn)();
}

Short of an accurate analysis, it appears that, for the purposes of
template argument deduction, int BB::aaa() is taken to be a member of
AA explicitly, even though you are providing its address as &BB::aaa.
Regards

Paul Bibbings

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]