Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Isn't this a conversion bug in gcc?

3 views
Skip to first unread message

DeMarcus

unread,
Jul 25, 2010, 7:56:30 PM7/25/10
to
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! ]

DeMarcus

unread,
Jul 26, 2010, 10:13:21 AM7/26/10
to
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?

Daniel Krügler

unread,
Jul 26, 2010, 10:11:37 AM7/26/10
to
On 26 Jul., 01:56, DeMarcus <use_my_alias_h...@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

Daniel Krügler

unread,
Jul 26, 2010, 1:48:35 PM7/26/10
to
On 26 Jul., 16:11, Daniel Krügler <daniel.krueg...@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

James Kanze

unread,
Jul 26, 2010, 1:46:18 PM7/26/10
to
On Jul 26, 12:56 am, DeMarcus <use_my_alias_h...@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

Daniel Krügler

unread,
Jul 26, 2010, 2:41:53 PM7/26/10
to
On 26 Jul., 16:13, DeMarcus <use_my_alias_h...@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


Johannes Schaub (litb)

unread,
Jul 26, 2010, 6:18:29 PM7/26/10
to
Daniel Krügler wrote:

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?

Nikolay Ivchenkov

unread,
Jul 26, 2010, 6:33:26 PM7/26/10
to
On 26 Jul, 21:46, James Kanze <james.ka...@gmail.com> wrote:
> On Jul 26, 12:56 am, DeMarcus <use_my_alias_h...@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).

Daniel Krügler

unread,
Jul 27, 2010, 12:46:11 AM7/27/10
to
On 27 Jul., 00:18, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:
> 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


Nikolay Ivchenkov

unread,
Jul 27, 2010, 10:45:49 AM7/27/10
to
On 27 Jul, 02:33, Nikolay Ivchenkov <ts...@mail.ru> wrote:
>
> template <class T>
> void X::f()
> { return 0; }

Correction:

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

On 27 Jul, 08:46, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:


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

Does the standard clearly differentiate instantiation of a function
prototype and instantiation of a function definition?

14.7/1:
The act of instantiating a function, a class, a member of a class
template or a member template is referred to as template
instantiation.

What does "instantiating a function" mean? For example, according to
12.8/3,

"A member function template is never instantiated to perform the copy
of a class object to an object of its class type. [Example:

struct S {
template<typename T> S(T);
};

S f();

void g() {
S a( f() ); // does not instantiate member template
}
—end example]"

What exactly is not instantiated? Prototype or definition only?
Probably, the prototype is meant (since during overload resolution
only prototypes are considered). But usually "instantiation of a
function" means instantiation of its definition (if the definition
exists).

Johannes Schaub (litb)

unread,
Jul 27, 2010, 5:48:29 PM7/27/10
to
Daniel Krügler wrote:

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.

Daniel Krügler

unread,
Jul 29, 2010, 9:48:30 AM7/29/10
to

I think we need to distinguish different questions (from
here on I concentrate on implicit instantiations of function
template, unless explicitly said otherwise):

a) When is a compiler allowed to instantiate a (function)
template?

b) When is finally the existence of the definition of an entity
required?

c) When is the instantiation process supposed to include
available definitions and when is it supposed to restrict to
non-defining declarations?

The answers to these questions highlight different aspects
of requirements.

ad a) During this discussion we already recognized several
situations where the standard describes that implicit
instantiations will or may happen. One critical example
mentioned by Johannes (referring to 14.7.1/9) is involved
with the question whether such a normative statement
implies further requirements, such as the existence of the
definition of the instantiated function template (There
is no such uncertainty in regard to class templates). My
assertion is, that the normative requirement or freedom to
perform instantiations *alone* does not necessarily lead
to the conclusion that the corresponding definitions are
required to exist.

ad b) The Standard also emphasizes the restriction to *required*
definitions. They are typically controlled by the ODR, and by some
further constraints, among them one important constraint involved
with function template instantiations within individual translation
units (see also my reply to Johannes as the end of this message).

14.7.1/2 does refer to *required* definitions:

"[..] the function template specialization is implicitly instantiated


when the specialization is referenced in a context that requires

a function definition to exist. [..]"

and similarly in [lex.phases]/1 b. 8:

"[..] Each translated translation unit is examined to produce a list
of required instantiations.[..]"

In regard to Johannes example the Standard is remarkably clear
that a pure virtual function does not require the existence of a
definition.

ad c) I agree that the Standard in general includes the instantiation
of definitions *when* they are required to exist and *when* they
are available. But there are two special situations, when only non-
defining declarations are supposed to be instantiated:

1) When a class template is implicitly instantiated, only the
declarations
of the member functions are instantiated, see 14.7.1/1:

"[..] The implicit instantiation of a class template specialization
causes
the implicit instantiation of the declarations, but not of the
definitions or
default arguments, of the class member functions, member classes,
static data members and member templates; and it causes the implicit
instantiation of the definitions of member anonymous unions. [..] "

[I'm not sure whether the requirement of "implicitly instantiating
the
declarations of member templates" is correct - it looks dubious to
me, because they still don't have any types or values available to
make this possible.]

2) During overload situations, *declarations* of function template
specializations may be instantiated as well, see 14.7.1/8 (emphasis
mine):

"If a function template or a member function template specialization
is used in a way that involves overload resolution, a *declaration*
of the specialization is implicitly instantiated (14.8.3)."

It would certainly be better, if the standard would here more
specifically speak of a "non-defining" declaration or "only
declarations"
to exclude the possible interpretation that a definition is required
or even considered when available. Fortunately the referenced
14.8.3/5 is provided:

"Only the signature of a function template specialization is needed
to enter the specialization in a set of candidate functions.
Therefore
only the function template declaration is needed to resolve a call
for
which a template specialization is a candidate."

A compiler is not required to perform this "overload declaration
instantiation", though, as 14.7.1/5 says:

"If the overload resolution process can determine the correct
function to call without instantiating a class template definition,
it is unspecified whether that instantiation actually takes place."

-----

The explanation in your last example is supposed to say that the
compiler is *not allowed* to generate the declaration

S::S<>(S); [1]

followed by further implications. E.g. if this declaration would be
feasible, the above usage would also require the need for an
definition instantiation.

If we look at another example:

struct S {
} s, *ps = &s;

template<class T> void f(T t) {
typename T::X x;
}

template<class T> void f(T* t) {
T::n * (*t);
}

typedef decltype(f(s)) type_1;
typedef decltype(f(ps)) type_2;

overload resolution happens, but this step may only produce the
(non-defining) declarations

void f<>(S);
void f<>(S*);

The compiler is not allowed to instantiate the function definitions,
here, because both function template specializations are not used
in a context that requires the definitions to exist. The code is also
well-formed, because both function templates *could* produce valid
definitions for some other template arguments (not for type S,
though). *If* a definition would be required, as for example in the
modified version:

int i = (f(s), 42);

the compiler will also attempt to instantiate the function
definition,
which is in sight here and will declare it as ill-formed due to the
missing type S::X.

Consider now:

struct S {};
extern S s;

template<class T> void f(T t);
template<class T> void f(T* t);

const int i = (f(s), 42);

int main() {}

First, overload resolution instantiates the specialization
declarations:

void f<>(S);
void f<>(S*);

Second, the *usage* of void f<>(S) in the definition of i does also
require the *need* for a definition of this function according to
the ODR (and that of object s of-course). *How* such a function
definition is instantiated, depends on the remaining program.

1) The definition is never instantiated: Violation of the ODR.

2) A *definition* is instantiated: Whether the instantiation is well-
formed and well-defined, depends on the way the specialization
is produced [In this example, it cannot be provided by an explicit
specialization defined elsewhere, because that must be declared
before used. An implicit instantiation by another translation unit
is also not sufficient, see below].

>From here I reply to Johannes Schaub's follow-up comments:

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

Exactly.

> Is there normative text that says that implicit instantiation of a
> function is valid even if its definition is absent, though?

I think this indirectly follows from 14.7.1/1 and 14.7.1/8 quoted
above (my bullet c). I would certainly agree that this is only
indirect,
but the Standard does usually not require the definition of anything,
unless specified explicitly, therefore I think this is at least a
reasonable interpretation.

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

I agree that the previous requirement should and need to be restored
(modulo export). It would also help, if the standard would sometimes
better express when in refers to non-defining instantiated
declarations
and when it refers to instantiated definitions. The requirement behind
14/8 is based on a need for an existing definition within the same
translation unit, if that definition is *required*. Declaration
instantiation
because of overload resolution alone does not lead to this need as
shown in earlier examples.

I would like to end with the remark that I don't want to deny that
the
standard could be a somewhat clearer in regard to implicit
instantiations, see e.g. core issue

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#212

for a good example of this lack of clearness in some situations.

HTH & Greetings from Bremen,

Daniel Krügler

[1] The notation I use here is only an approximation of what the
compiler produces. It shall not be understood to declare an
explicit instantiation or an explicit specialization, for example.

Daniel Krügler

unread,
Jul 29, 2010, 2:59:58 PM7/29/10
to
On 29 Jul., 15:48, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:

> ad c) I agree that the Standard in general includes the instantiation
> of definitions *when* they are required to exist and *when* they
> are available. But there are two special situations, when only non-
> defining declarations are supposed to be instantiated:
>
> 1) When a class template is implicitly instantiated, only the
> declarations
> of the member functions are instantiated, see 14.7.1/1:
>
> "[..] The implicit instantiation of a class template specialization
> causes
> the implicit instantiation of the declarations, but not of the
> definitions or
> default arguments, of the class member functions, member classes,
> static data members and member templates; and it causes the implicit
> instantiation of the definitions of member anonymous unions. [..] "
>
> [I'm not sure whether the requirement of "implicitly instantiating
> the declarations of member templates" is correct - it looks dubious
> to me, because they still don't have any types or values available
> to make this possible.]

I believe that I'm misinterpreting the normative wording with
my comment:

The above paragraphs says what we expect: No definitions
or default arguments of the members (including the member
templates) are to be instantiated. When I read it during
my quotation I interpreted it (wrongly) to say that the
declarations of the member templates will be instantiated.

This correction should not influence anything else from the
previous posting.

- Daniel

Nikolay Ivchenkov

unread,
Jul 29, 2010, 8:22:35 PM7/29/10
to
On 29 Jul, 17:48, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:
>

> ad c) I agree that the Standard in general includes the instantiation
> of definitions *when* they are required to exist and *when* they
> are available.

#include <iostream>

int n = 0;

template <class T>
struct B
{
B()
{
if (n)
f();
// pure function call
// (see the suggested resolution for core issue 230)
}
virtual void f() = 0;
};

template <class T>
void B<T>::f()
{ std::cout << "B<T>::f()\n"; }

struct D : B<int>
{
D()
{ static_cast<B<int> &>(*this).f(); }
void f()
{ std::cout << "D::f()\n"; }
};

int main()
{
std::cin >> n;
D();
}

A definition of B<int>::f is not required to be exist. Thus, we can't
apply 14.7.1/2

"Unless a function template specialization has been explicitly
instantiated or explicitly specialized, the function template


specialization is implicitly instantiated when the specialization is
referenced in a context that requires a function definition to exist."

Must the definition of B<int>::f be instantiated?

Daniel Krügler

unread,
Jul 30, 2010, 11:18:31 AM7/30/10
to

Yes.

Even though B<int>::f is not required to exist in any general program
it is required to exist in this particular program, because it is
still used
in the sense of the *general* requirements specified in 3.2/2:

"An expression is potentially evaluated unless it is an unevaluated
operand (Clause 5) or a subexpression thereof. A variable or non-
overloaded function whose name appears as a potentially-evaluated
expression is used unless it is an object that satisfies the
requirements for appearing in a constant expression (5.19)
and the lvalue-to-rvalue conversion (4.1) is immediately applied.[..]"

The example invokes the constructor of B as part of a potentially
evaluated expression. Note that the refining sentence:

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

does not declare a pure virtual function as *unused*, it only declares
*any* non-pure virtual function as *used*. This is a big difference,
because it does not make the former requirements invalid.

HTH & Greetings from Bremen,

Daniel Krügler


Nikolay Ivchenkov

unread,
Jul 30, 2010, 4:18:35 PM7/30/10
to
On 30 Jul, 19:18, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:

>
> Even though B<int>::f is not required to exist in any general program

Did you mean "_a definition of_ B<int>::f is not required to exist"?

> it is required to exist in this particular program, because it is
> still used
> in the sense of the *general* requirements specified in 3.2/2:
>
> "An expression is potentially evaluated unless it is an unevaluated
> operand (Clause 5) or a subexpression thereof. A variable or non-
> overloaded function whose name appears as a potentially-evaluated
> expression is used unless it is an object that satisfies the
> requirements for appearing in a constant expression (5.19)
> and the lvalue-to-rvalue conversion (4.1) is immediately applied.[..]"
>
> The example invokes the constructor of B as part of a potentially
> evaluated expression. Note that the refining sentence:
>
> "A virtual member function is used if it is not pure."
>
> does not declare a pure virtual function as *unused*, it only declares
> *any* non-pure virtual function as *used*.

I can't accept this explanation. Lets consider more simple example:

struct AbstractBase
{


virtual void f() = 0;
};

struct Derived : AbstractBase
{
void f() { /*...*/ }
};

void g(AbstractBase &x)
{
x.f();
}

int main()
{
Derived d;
g(d);
}

If the function AbstractBase::f is used, we shall apply 3.2/3:

"Every program shall contain exactly one definition of every non-
inline function or object that is used in that
program; no diagnostic required."

So, the program above would be ill-formed and in general undefined
pure virtual functions would be almost useless? Then the wording

"A pure virtual function need be defined only if explicitly called
with the qualified-id syntax (5.1)." (10.4/2)

is wrong?

> This is a big difference,
> because it does not make the former requirements invalid.

In any case the specification is bad.

I can point out another issue:

namespace N
{
struct A {};
void f(A, int) { /*...*/ }
}

void f(N::A, long) { /*...*/ }

int main()
{
f(N::A(), 0);
}

Are functions N::f and ::f overloaded? No? Then which functions are
used according to literal interpretation of 3.2/2? Both? :-)

0 new messages