Re: Is it a g++-4.1 bug ?
On 3/14/07 8:29 PM, in article
1173913213.689912.290410@y66g2000hsf.googlegroups.com, "Daniel Kr?gler"
<daniel.kruegler@googlemail.com> wrote:
Manuel.Yg...@inrialpes.fr schrieb:
template<typename T>
struct test
{
T o;
template<typename I>
struct inner
{
I* ptr;
const inner<I>& operator*() const;
[..]
};
typedef inner< test<T> > const_iterator;
};
template<typename T>
template<typename I>
const test<T>::inner<I>& test<T>::inner<I>::operator*() const
{
return *this;
}
For me it does not compile, the compiler complains:
invalid declarator before '&' token in the operator*() definition.
The compiler is right, the shown out-of-class definition of
operator* should not compile, v.i.
The compiler is wrong, the shown out of class definition of operator*()
should compile as is.
By providing the complete qualification you stumble
accross two problems for this specification:
By providing the complete qualification you stumble across two problems that
gcc has with definitions of this sort.
template<typename T>
template<typename I>
const test<T>::inner<I>& ...
1) For proper interpretation what "test<T>::inner"
means you are required to tell the compiler that
inner is a type (and not another non-type name).
Therefore you need a leading typename:
The "typename" keyword would be needed only if "inner" a) named a type and
b) depended upon a template parameter for its successful resolution. But
because "inner" names a template and not a type, and because the inner class
template is defined within the "test" class template itself (and not in the
context of any type), the "typename" keyword should not appear here.
template<typename T>
template<typename I>
const typename test<T>::inner<I>& ...
This need is explained in 14.6/2 ff.
2) Now the compiler understands that test<T>::inner
is a type and the next parsing problem is the following
< character, which *could* be interpreted as less
operator. To help then compiler you need to say that
the following is a template-id:
The compiler knows that inner is not a type, but a template. The compiler
also knows that inner<I> must be a template-id because the preceding
"template <typename I>" announces it as such.
template<typename T>
template<typename I>
const typename test<T>::template inner<I>& ...
Because "typename" and "template" identify different type-dependent names,
no one name would ever require that both keywords be applied to it. So the
fact that gcc would requires both "typename" and "template" for the name
"inner" could not be a valid C++ requirement - but could only be caused by a
bug in the compiler.
This second problem is explained in 14.2/4:
"When the name of a member template specialization appears
after . or -> in a postfix-expression, or after nested-name-specifier
in a qualified-id, and the postfix-expression or qualified-id
explicitly
depends on a template-parameter (14.6.2), the member template
name must be prefixed by the keyword template. Otherwise the
name is assumed to name a non-template".
Again, "inner" has no dependency on any template parameter. So "template" is
just as inappropriate as "typename" in this example.
Afaik both "helper" keywords are required in this situation.
Interestingly even modern compilers seem to accept the
incomplete versions, e.g.
- Comeau 4.3.8 Alpha as well as 4.3.3 Beta accept your
*original* version. This is IMO an error and should be reported.
There is no error in the original program, so both Comeau and EDG accept it.
Once this bug is fixed, the gcc compiler will follow suit.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]