Re: gcc-4.4.3 failure in rejecting instantiation?
On Jun 19, 11:15 pm, Paul Bibbings <paul.bibbi...@gmail.com> wrote:
I've been working on some code (not mine) that relies on the
following motif leading to a compilation failure, with
sensible output, at line 17 (below). The trouble is, with
gcc-4.4.3, it *doesn't* fail:
template<typename T>
struct Error { };
template<typename T>
struct A
{
static const int i = Error<T>::TempArgMustBeInt; // line: 7
};
template<>
struct A<int>
{ };
int main()
{
A<int> A_int;
A<char> A_char; // line: 17
}
I'm thinking that it probably should (or, I have no immediate
understanding of why it wouldn't); whoever wrote the original code
(probably some while ago) thought it should; and, Comeau seems to
agree:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions
"ComeauTest.c", line 7: error: class "Error<char>" has no member
"TempArgMustBeInt"
static const int i = Error<T>::TempArgMustBeInt;
^
detected during instantiation of class "A<T> [with T=char]" a=
t
line 17
// ...
1 error detected in the compilation of "ComeauTest.c".
What does anyone else think?
I think the standard is a bit vague about this. According to
the standard, a static data member is only instantiated if it is
used. (See =A714.7.1.) I don't see anything in your code which
would require an instance of A::i, so the definition of A::i
should not be instantiated. Which is good, because you don't
provide a definition (in the sense of the standard). On the
other hand, this is the only case I know in the standard where
a declaration which is not a definition can contain an
initializer---is the initializer considered part of the
declaration, or a pre-definition, of sorts? In the first case,
it should be instantiated (triggering the error); in the second,
it shouldn't be instantiated unless i is actually used.
I think the classical way of doing this is something like:
template <typename T>
struct A
{
enum { error = sizeof(Error<T>::whatever) };
};
The enum constant must be instantiated any time the class is.
--
James Kanze