Topic: must template definitions sometimes cause instantiations?
Author: virtanea@mustatilhi.cs.tut.fi (Virtanen Antti)
Date: Thu, 20 Oct 2005 02:16:10 GMT Raw View
On 2005-10-11, Ronald Garcia <ron.garcia@gmail.com> wrote:
> The book goes on to note that even without instantiating Tricky, a
> compiler can complain about the presence of "Danger<0>" in the
> definition of the "error()" member function. However, it's not clear
> to me whether or not a standard compliant compiler is required to
> report this.
According to the book you refer to, C++ Templates The Complete Guide,
it is required:
"If it weren't commented out, the member error() would trigger an error
while the template is compiled because the use of Danger<0> requires a
complete definition of the class Danger<0>, and generating that
class..."
"This is the case even though the member error() may not be used and
therefore may not be instantiated."
I am not qualified to say what the C++ Standard states on the matter,
but if I understood correctly the authors of the book (David
Vandevoorde and Nicolai Josuttis) have been part of the standard
committee. This suggests to me that they know what the standard says
and what it's supposed to say.
--
// Antti Virtanen -//- http://www.students.tut.fi/~virtanea -//- 050-4004278
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: richard_corden@hotmail.com (Richard Corden)
Date: Thu, 20 Oct 2005 14:53:05 GMT Raw View
Hi,
Ronald Garcia wrote:
[...]
> However, it's not clear
> to me whether or not a standard compliant compiler is required to
> report this. I have examined Chapter 14 of the standard and the text
> regarding implicit instantiation seems rather vague (quite possibly in
> order to lend flexibility to implementators).
Checkout 14.6/7.
A standard compliant compiler does not need to report this. It is a
quality of implementation issue. However, the code will always be
ill-formed, i.e. adding an explicit specialisation of Danger<0> after
the definition of Tricky will still result in an ill-formed program.
As you point out, it is to allow flexibility to implementers. Some
implementations perform very little checking on the template definition
and leave it until instantiation, others perform lots of *early* checking.
The more recent drafts of the C++-0X standard have text which explicitly
relate to your example, however, no diagnostic is required:
... If a type used in a non-dependent name is incomplete at the point
at which a template is defined but is complete at the point at which
an instantiation is done, and if the completeness of that type affects
whether or not the program is well-formed or affects the semantics of
the program, the program is ill-formed; no diagnostic is required.
Regards,
Richard
--
Richard Corden
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com
Date: 21 Oct 2005 05:20:16 GMT Raw View
Richard Corden wrote:
> Hi,
>
> Ronald Garcia wrote:
>
> [...]
>
> > However, it's not clear
> > to me whether or not a standard compliant compiler is required to
> > report this. I have examined Chapter 14 of the standard and the text
> > regarding implicit instantiation seems rather vague (quite possibly in
> > order to lend flexibility to implementators).
>
> Checkout 14.6/7.
>
> A standard compliant compiler does not need to report this. It is a
> quality of implementation issue. However, the code will always be
> ill-formed, i.e. adding an explicit specialisation of Danger<0> after
> the definition of Tricky will still result in an ill-formed program.
>
> As you point out, it is to allow flexibility to implementers. Some
> implementations perform very little checking on the template definition
> and leave it until instantiation, others perform lots of *early* checking.
You are right of course. However, it may be worth noting that although
a compiler is at liberty not to check a template until it is
instantiated,
when it _is_ instantiated, it still must do the checks "as if" the
checks
had been done at the point of definition.
The following example must therefore elicit a diagnostic:
template<typename T> struct S;
template<typename T> void f() {
S<int> s; // Error: S<int> incomplete
}
template<> struct S<int> {}; // Too late.
int main() {
f<int>(); // Force point of instantiation
}
Just about every compiler that does not check a template at the point
of definition gets this wrong. This is because they incorrectly
perform
the tests from a later point of view.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Jeremy" <jeremy.siek@gmail.com>
Date: 22 Oct 2005 14:00:02 GMT Raw View
Just curious, does the program become well formed if f() is
changed as follows:
template<typename T> void f() {
S<T> s;
}
I believe it does because the point of instantiation for S<int> will
now be immediately prior to main, which is after the explicit
specialization of S<int>.
-Jeremy
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com
Date: Sat, 22 Oct 2005 21:11:25 CST Raw View
Jeremy wrote:
> Just curious, does the program become well formed if f() is
> changed as follows:
>
> template<typename T> void f() {
> S<T> s;
> }
>
> I believe it does because the point of instantiation for S<int> will
> now be immediately prior to main, which is after the explicit
> specialization of S<int>.
You're right that it makes the example valid, but the details are
slightly more subtle. First, the point of intantiation (POI) of
f<int>() is immediately _after_ the the definition of main.
(The standard words for this are in 14.6.4.1.)
Note that when the standard talks about instantiations, it always
talks about the instantiation of _definitions_ (or _expressions_ in
the case of default arguments). The standard doesn't formally
talk about the instantiation of declarations that aren't definitions
(sometimes called "partial instantiation" among compiler writers),
although it probably should.
S<int> doesn't have a POI, because it is explicitly specialized.
Had it not been explicitly specialized, it's POI in the modified
example would have been just before the POI of f<int>() (but
after the definition of main().).
Mostly these considerations matter little to a programmer.
They are observable, however, in some odd codes dealing with
certain injected names such as friend declaration and elaborated
type names.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Ronald Garcia" <ron.garcia@gmail.com>
Date: Tue, 11 Oct 2005 16:46:34 CST Raw View
Hello,
In the book C++ templates, there is an example program (p. 144) that
has a snippet of code along the lines of the following:
template <int N>
struct Danger {
typedef char Block[N];
};
template <class T, int N>
struct Tricky {
void error() { Danger<0> boom; }
};
The book goes on to note that even without instantiating Tricky, a
compiler can complain about the presence of "Danger<0>" in the
definition of the "error()" member function. However, it's not clear
to me whether or not a standard compliant compiler is required to
report this. I have examined Chapter 14 of the standard and the text
regarding implicit instantiation seems rather vague (quite possibly in
order to lend flexibility to implementators).
I have noticed that GCC 3.3 accepts this program without complaint, but
Comeau's online compiler complains when in --strict mode.
Is it required or optional for a standards-compliant compiler to detect
the above error (presumably by instantiating Danger<0>). Either way,
could someone point me to the language in the standard that covers this
particular case, or more generally how to treat nondependent references
to template specializations in template declarations and definitions?
Thanks,
ron
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 11 Oct 2005 23:20:14 GMT Raw View
Ronald Garcia wrote:
> Hello,
>
> In the book C++ templates, there is an example program (p. 144) that
> has a snippet of code along the lines of the following:
>
> template <int N>
> struct Danger {
> typedef char Block[N];
> };
>
> template <class T, int N>
> struct Tricky {
>
> void error() { Danger<0> boom; }
>
> };
>
>
> The book goes on to note that even without instantiating Tricky, a
> compiler can complain about the presence of "Danger<0>" in the
> definition of the "error()" member function. However, it's not clear
> to me whether or not a standard compliant compiler is required to
> report this. I have examined Chapter 14 of the standard and the text
> regarding implicit instantiation seems rather vague (quite possibly in
> order to lend flexibility to implementators).
>
> I have noticed that GCC 3.3 accepts this program without complaint, but
> Comeau's online compiler complains when in --strict mode.
>
> Is it required or optional for a standards-compliant compiler to detect
> the above error (presumably by instantiating Danger<0>). Either way,
> could someone point me to the language in the standard that covers this
> particular case, or more generally how to treat nondependent references
> to template specializations in template declarations and definitions?
>
As Danger<0> names a non-dependent type, it must be bound at the point
of use (14.6.3/1), that is immediately. As the context in which
Danger<0> is used requires a completely-defined object type, this
triggers implicit instantiation (14.7.1/1). So the code is definetely
ill-formed (but it seems that you already agreed on this point).
There is a comment in the example of 14.6.3/1, which is non-normative,
however, that says: "this could be diagnosed either here or at the point
of instantiation", so it seems that the intent is to explicitly allow
the diagnostic to be deferred. I could not find any other statement
requiring the diagnostic to be emitted at the point of declaration. If
there is one, we should then file a DR to remove the misleading
non-normative comment from 14.6.3/1.
Just my opinion,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]