From: DeMarcus on
Hi,

Consider this template.

template<typename T>
struct Q
{
virtual Q* fnc() { return new T; }
};

If I now declare a variable like this

Q<int> qi;

I get the following from gcc 4.5.0.
"error: cannot convert 'int*' to Q<int>*' in return".

That seems perfectly correct. But now try this

struct A : Q<int>
{
};

and it complies perfectly fine with gcc 4.5.0!!! That must be a bug, right?


Thanks,
Daniel

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

From: DeMarcus on
On 2010-07-26 01:56, DeMarcus wrote:
> Hi,
>
> Consider this template.
>
> template<typename T>
> struct Q
> {
> virtual Q* fnc() { return new T; }
> };
>
> If I now declare a variable like this
>
> Q<int> qi;
>
> I get the following from gcc 4.5.0.
> "error: cannot convert 'int*' to Q<int>*' in return".
>
> That seems perfectly correct. But now try this
>
> struct A : Q<int>
> {
> };
>
> and it complies perfectly fine with gcc 4.5.0!!! That must be a bug,
right?
>
>
> Thanks,
> Daniel
>

Ok, I realized I needed a bit compiler knowledge refresh. I found out
that it's not until A is instantiated that the error will show up.

Can you please confirm that the following is true?

If I do the this

struct A : Q<A>
{
};

the compiler will be able to deduce that A is a subclass of Q since the
compiler compiles in two steps; first it goes through all the
declarations and sees everything is ok, then it goes through all the
definitions, and it will then find out that 'return T' is valid
according to the already processed declarations where it says that A
inherits from Q. (is there a paragraph in the standard confirming this?)


Can you confirm that the following is correct as well?

I extended the template to look like this. Note, I changed the fnc()
return type be of type T.

template<typename T, class Base>
struct Q : Base
{
virtual T* fnc() { return new T; }
};

I extended A with some inheritance.

struct A : Q<A, EmptyClass>
{
};

struct B : Q<B, A>
{
};

The compiler will give me an error saying that B is not a covariant
return type of A (while it actually is). Is the compiler unable to
deduce the covariance because of the fact that it's only part of the
declaration step?
(would the compiler be able to find out, or do we break any rule by
doing that?)

If I remove the keyword 'virtual' it will work because the compiler then
applies function overriding instead.


Am I correct about how the compiler works?

Thanks,
Daniel


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

From: Daniel Krügler on
On 26 Jul., 01:56, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Hi,
>
> Consider this template.
>
> template<typename T>
> struct Q
> {
> virtual Q* fnc() { return new T; }
>
> };
>
> If I now declare a variable like this
>
> Q<int> qi;
>
> I get the following from gcc 4.5.0.
> "error: cannot convert 'int*' to Q<int>*' in return".
>
> That seems perfectly correct. But now try this
>
> struct A : Q<int>
> {
>
> };
>
> and it complies perfectly fine with gcc 4.5.0!!! That must be a bug,
right?

This is not a bug, but an explicit freedom, the Standard
provides to implementors of templates: In contrast to
non-virtual functions, virtual functions may lead to
an immediate member instantiation, even, if not
used, see 14.7.1/9 (Both C++03 and FCD):

"An implementation shall not implicitly instantiate a function
template, a member template, a non-virtual member function,
a member class, or a static data member of a class template
that does not require instantiation. It is unspecified whether
or not an implementation implicitly instantiates a virtual
member function of a class template if the virtual member
function would not otherwise be instantiated."

HTH & Greetings from Bremen,

Daniel Kr�gler


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

From: Daniel Krügler on
On 26 Jul., 16:11, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> In contrast to non-virtual functions, virtual functions
> may lead to an immediate member instantiation, even, if not
> used, see 14.7.1/9 (Both C++03 and FCD):

And to be more precise: Any declaration of a virtual
function is considered as a "use", see 3.2/2:

"A virtual member function is used if it is not pure."

HTH & Greetings from Bremen

Daniel Kr�gler


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

From: James Kanze on
On Jul 26, 12:56 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> Consider this template.

> template<typename T>
> struct Q
> {
> virtual Q* fnc() { return new T; }
> };

> If I now declare a variable like this

> Q<int> qi;

> I get the following from gcc 4.5.0.
> "error: cannot convert 'int*' to Q<int>*' in return".

> That seems perfectly correct. But now try this

> struct A : Q<int>
> {
> };

> and it complies perfectly fine with gcc 4.5.0!!! That must be
> a bug, right?

No. The code is perfectly legal (and must be accepted by the
compiler) as long as you don't try to instantiate A. The
function Q<int>::fnc should only be instantiated (triggering the
error) if it is used. A virtual function is "used" if there is
an instance of the type, but as long as there is no instance,
a compiler is not allowed to instantiate it.

(A really clever compiler might be able to warn that there is no
type T which could result in a valid fnc, but it can't trigger
an error unless it is actually called on to instantiate fnc.)

--
James Kanze

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