Re: typedef in template class
Am 11.03.2011 20:26, schrieb Jonathan Thornburg:
[N.b.: This is *not* a homework exercise.]
I'm encountered some strange-to-me behavior when trying to use typedefs
(defined in a template class) in other templates, and I'm wondering
if someone can point me to what's going on, i.e., why what I expected
to be legal code is being rejected by my compiler (g++ 4.2.4).
To be specific, consider the following C++ code:
#include<complex> // 1
// 2
template<typename fp> // 3
class A // 4
{ // 5
public: // 6
typedef std::complex<fp> field; // 7
}; // 8
// 9
template<typename fp> // 10
void foo() // 11
{ // 12
typedef A<float>::field float_field; // 13
typedef A< fp>::field fp_field; // 14
A<float>::field x; // 15
A< fp>::field y; // 16
} // 17
// 18
template<typename fp> // 19
class B // 20
{ // 21
public: // 22
typedef A<float>::field float_field; // 23
typedef A< fp>::field fp_field; // 24
A<float>::field x_; // 25
A< fp>::field y_; // 26
}; // 27
The idea here is that class A<fp> defines a (public) typedef at line 7,
which I then try to use in a template function and a template class.
Trying to compile this code using g++ 4.2.4 gives the following error
messages:
% /usr/local/bin/g++ -W -Wall -g -c template_typedef.cc
template_typedef.cc: In function 'void foo()':
template_typedef.cc:14: error: too few template-parameter-lists
template_typedef.cc:16: error: expected `;' before 'y'
template_typedef.cc: At global scope:
template_typedef.cc:24: error: type 'A<fp>' is not derived from type 'B<fp>'
template_typedef.cc:24: error: expected ';' before 'fp_field'
template_typedef.cc:26: error: type 'A<fp>' is not derived from type 'B<fp>'
template_typedef.cc:26: error: expected ';' before 'y_'
%
In other words, each reference to A<float>::field is accepted by
the compiler, while each reference to A<fp>::field gives an error.
My question is, why -- within the scope of "template<typename fp>" --
is A<fp>::field not a valid type?
The reason for these different cases is [temp.res] p. 2:
"A name used in a template declaration or definition and that is
dependent on a template-parameter is assumed not to name a type unless
the applicable name lookup finds a type name or the name is qualified
by the keyword typename."
This rules affects all the cases where the compiler complained about,
e.g. A<fp>::field is a dependent name, because fp is a template
parameter, but A<float>::field is non-dependent. The reason for this
rule is related to the fact, that in the context of a dependent name the
compiler has no way to know whether e.g. A<fp>::field *really* refers to
a type or not. This is so, because you could define some specialization
A<X> where field could have a completely different meaning, e.g. consider:
template<>
struct A<bool> {}; // No typename "field" at all
template<>
struct A<int> {
static long field; // "field" is not a type
};
In non-dependent situations as in A<float>::field the can verify
immediately whether the specialization A<float> contains the name
"field" and what the meaning of this name is.
Let me add that your observation is partially mentioned in the FAQ -
albeit a bit indirectly and concentrated on base-classes:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
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! ]