Re: Isn't this a conversion bug in gcc?
On 27 Jul., 16:45, Nikolay Ivchenkov <ts...@mail.ru> wrote:
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).
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.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]