From: Daniel Krügler on
On 26 Jul., 16:13, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> On 2010-07-26 01:56, DeMarcus wrote:
>
[..]

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

In your example that depends on the concrete implementation
as shown in my previous posting.

> 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

At which point? Not within the definition of Q<A>.

> 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?)

No, see below.

> 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>
> {
> };

This is OK, because T can be incomplete, when
the parser sees the declaration

T* Q<>::fnc();

T is required to be complete within the definition
of the function body, but that is not relevant for
the compiler when parsing the definition of Q<A,
EmptyClass>, where only the declaration of the
members is needed. The role of the second template
parameter is that of a base class, but a type must be
complete to be used as a base class. I assume that
EmptyClass is defined (not just declared), which makes
it feasible for a base class.

> 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?

In this example you are attempting to define
a class Q<B, A>, that has a base class A, which
again derives from Q<A, EmptyClass>. The base
class is complete and effectively has a virtual
function

A* A<>::fnc();

Now when you attempt to instantiate Q<B, A>
we have the same situation as we had in the example
before: Within Q<B, A> B is an incomplete type.
But since you are now overriding the base class,
the standard requires that the return type is a
derived class of the pointee used in the super
class. Since B is incomplete within Q<B, A>,
this declaration is ill-formed according to
10.3/6 (FCD):

"If the return type of D::f differs from the return type
of B::f, the class type in the return type of D::f shall
be complete at the point of declaration of D::f or shall
be the class type D."

Note that it says: "at the point of the declaration
of D::f", which is not satisfied in your example.

> (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?

Not really ;-)

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: Johannes Schaub (litb) on
Daniel Krügler wrote:

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

This was precisely the paragraph i was arguing at
http://groups.google.com.mt/group/comp.std.c++/browse_thread/thread/7a784b1aa5277c71
using the interpretation you use in this post :) Your answer back then was
different: You seemed to say that it would not imply instantiating a
definition.

Did i misunderstand your statement back then? I still don't understand it,
fwiw. The "It is unspecified ..." part seems totally redundant to me,
because the ODR rule you quoted already requires instantiation for non-pure
virtual functions, and does not require it for pure functions. What would be
different if we would remove the "It is unspecified ...." sentence?

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

From: Nikolay Ivchenkov on
On 26 Jul, 21:46, James Kanze <james.ka...(a)gmail.com> wrote:
> 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.

That's very strange explanation. 'A' is not a template. Actually we
have to apply the following rules with respect to Q<int>:

14.7.1/1:
Unless a class template specialization has been explicitly
instantiated (14.7.2) or explicitly specialized (14.7.3), the class
template specialization is implicitly instantiated when the
specialization is referenced in a context that requires a completely-
defined object type or when the completeness of the class type affects
the semantics of the program.

10/1:
The class-name in a base-specifier shall not be an incompletely
defined class (clause 9)

Since the specialization Q<int> is not explicitly instantiated nor
explicitly specialized, and it is used as a base-specifier, it shall
be completely defined class and it is implicitly instantiated. Then
the following rule applies:

14.7.1/9:
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.

> (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.)

If my understanding of the rules is correct, whether a valid
specialization of Q<T>::fnc can exist depends on implementation's
choice. Obviously, T and Q<T> are distinct types, so the conversion
from T* to Q<T>* is possible only if T is derived from Q<T>:

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

// point of instantiation for Q<D>
// possible point of instantiation for Q<D>::fnc

struct D : Q<D>
{
// ....
};

If an implementation implicitly instantiates Q<D>::fnc, the point of
instantiation for Q<D>::fnc is located as marked above (according to
14.6.4.1/4). At this point the class D is still incomplete, so the new-
expression would be invalid. Other points of instantiation for
Q<D>::fnc can be located after the definition of D.

Otherwise, all points of instantiation (if they exist) for Q<D>::fnc
are located after the definition of D, and the function definition is
correct.

There is also one very unclear rule:

14.6/7:
"If no valid specialization can be generated for a template
definition, and that template is not instantiated, the template
definition is ill-formed, no diagnostic required."

According to literal interpretation, the following code is ill-formed

template <class T>
class X
{
void f();
};

// template definition
template <class T>
void X::f()
{ return 0; }

but we can't apply this rule to the next code:

template <class T>
class X
{
// not a template definition
void f()
{ return 0; }
};

Probably that's a defect in the standard (and in C++0x draft), so an
implementation could consider

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

as ill-formed code (according to its choice with respect to implicit
instantiation of virtual functions).

--
[ 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 27 Jul., 00:18, "Johannes Schaub (litb)" <schaub-johan...(a)web.de>
wrote:
> Daniel Kr�gler wrote:
> > On 26 Jul., 01:56, 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?
>
> > 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."
>
> This was precisely the paragraph i was arguing athttp://groups.google.com.mt/group/comp.std.c++/browse_thread/thread/7...
> using the interpretation you use in this post :) Your answer back then was
> different: You seemed to say that it would not imply instantiating a
> definition.
>
> Did i misunderstand your statement back then? I still don't understand it,
> fwiw. The "It is unspecified ..." part seems totally redundant to me,
> because the ODR rule you quoted already requires instantiation for non-pure
> virtual functions, and does not require it for pure functions. What would be
> different if we would remove the "It is unspecified ...." sentence?

The example in our former discussion involved a *pure*
virtual function, but this is not the case in the OP's
example.

14.7.1 does not require the existence of any definitions
at all. The rules which finally require the existence of
a function are given by 3.2/3+4 which do clearly say that
a pure-virtual function is not considered as used and does
not require any definition of those to exist, and additional
in regard this discussion by 10.3/9:

"A virtual function declared in a class shall be defined,
or declared pure (10.4) in that class, or both; but no
diagnostic is required (3.2)."

Returning to 14.7.1, the effect of the requirements is
that an implementation may instantiate all virtual
function *declarations* and it also may instantiate all
function *definition* it finds - this does not mean
that this process is *requiring* the definitions to exist
- this is all left to the ODR and 10.3/9!

Thus, there is no reason to assume that suddenly 14.7.1
would imply the requirement for a definition of a pure
virtual function, that is otherwise explicitly omitted.

Returning to the OP's example: The fact, that an
implementation *may* instantiate virtual function
declarations and definitions (if they exist) has
the effect that it can diagnose the ill-formed code -
Nikolay gave a nice sequence of references of the
normative wording which explains this more precisly
as I did.

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: Johannes Schaub (litb) on
Daniel Kr�gler wrote:

> On 27 Jul., 00:18, "Johannes Schaub (litb)" <schaub-johan...(a)web.de>
> wrote:
>> Daniel Kr�gler wrote:
>>> On 26 Jul., 01:56, 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?
>>
>>> 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."
>>
>> This was precisely the paragraph i was arguing
>>
athttp://groups.google.com.mt/group/comp.std.c++/browse_thread/thread/7...
>> using the interpretation you use in this post :) Your answer back then
>> was different: You seemed to say that it would not imply instantiating a
>> definition.
>>
>> Did i misunderstand your statement back then? I still don't understand
>> it, fwiw. The "It is unspecified ..." part seems totally redundant to me,
>> because the ODR rule you quoted already requires instantiation for
>> non-pure virtual functions, and does not require it for pure functions.
>> What would be different if we would remove the "It is unspecified ...."
>> sentence?
>
> The example in our former discussion involved a *pure*
> virtual function, but this is not the case in the OP's
> example.
>
> 14.7.1 does not require the existence of any definitions
> at all. The rules which finally require the existence of
> a function are given by 3.2/3+4 which do clearly say that
> a pure-virtual function is not considered as used and does
> not require any definition of those to exist, and additional
> in regard this discussion by 10.3/9:
>
> "A virtual function declared in a class shall be defined,
> or declared pure (10.4) in that class, or both; but no
> diagnostic is required (3.2)."
>
> Returning to 14.7.1, the effect of the requirements is
> that an implementation may instantiate all virtual
> function *declarations* and it also may instantiate all
> function *definition* it finds - this does not mean
> that this process is *requiring* the definitions to exist
> - this is all left to the ODR and 10.3/9!
>
> Thus, there is no reason to assume that suddenly 14.7.1
> would imply the requirement for a definition of a pure
> virtual function, that is otherwise explicitly omitted.
>
> Returning to the OP's example: The fact, that an
> implementation *may* instantiate virtual function
> declarations and definitions (if they exist) has
> the effect that it can diagnose the ill-formed code -
> Nikolay gave a nice sequence of references of the
> normative wording which explains this more precisly
> as I did.
>

Ah thanks, i think i understand it now. The difference that it makes is to
pure virtual functions. If there is a definition of the pure virtual
function, the definition may be instantiatede even if it's not used. If
there is no definition, the text imposes no other requirements.

Is there normative text that says that implicit instantiation of a function
is valid even if its definition is absent, though? Refering to Nikolay's
most recent reply to you: If the text talks about implicitly instantiating a
definition (which i think it does - because a declaration of it is
instantiated anyway), what normative text grants for that implicit
instantiation to be valid even if that definition cannot be located because
it doesn't exist? I rather find the opposite. 14/8 says:

"A non-exported template must be defined in every translation unit in which
it is implicitly instantiated (14.7.1), unless the corresponding
specialization is explicitly instantiated (14.7.2) in some translation unit;
no diagnostic is required."

This is gonna removed by C++0x, but i haven't found other wording that would
say something different about implicit instantiation of function
definitions.

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