This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: c++/3634: partial specialization envolving nested classes is broken
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: Ewgenij Gawrilow <gawrilow at math dot tu-berlin dot de>, gcc-bugs at gcc dot gnu dot org
- Date: Wed, 21 Nov 2001 21:05:16 +0700
- Subject: Re: c++/3634: partial specialization envolving nested classes is broken
- References: <20011117084413.27865.qmail@sourceware.cygnus.com>
[Get raw message]
At 10:12 19/11/01 +0100, Ewgenij Gawrilow wrote:
> >
> > Synopsis: partial specialization envolving nested classes is broken
> >
> > State-Changed-From-To: open->closed
> > State-Changed-By: lerdsuwa
> > State-Changed-When: Sat Nov 17 00:44:13 2001
> > State-Changed-Why:
> > Not a bug. typename outer<T>::inner is a non-deduce context.
> > The compiler is not allowed to deduce that 'T' is 'int'. So
> > the partial specialization is never used by gcc.
> >
>Sorry, I can't agree with this argumentation. There is nothing to deduce
>here. The only thing the compiler has to check is whether the template
>argument is a local class `inner' of ANY instance of a given template class
>`outer'. I think, this could be done without any type deduction,
>since the internal description of `inner' surely contains some kind
>of reference to its containing class.
But it's how specialization works. To decide which template to use (primary,
partial specialization, specialization), template argument deduction is used.
The rules for that are specified in the C++ standard.
Now, about figuring out the outer class based on the inner class, there is
problem with several such cases. So the standard chose to disallow it.
Here is an example of problematic case:
struct A {};
template <class T> struct outer {
typedef A inner;
}
Now 'outer<T>::inner' does not depend on 'T'. So 'outer<int>::inner' is
the same as 'outer<char>::inner', or 'outer<std::vector<int> >::inner'.
They all refer to the same 'A'. You cannot tell what 'T' actually is.
>If you forbid partial specializations for local classes, how should
>we write traits classes for iterators, which are most naturally defined
>as local classes of their containers?
The inner class can contain information about its outer class, for example
template <class T> struct outer {
struct inner {
typedef T type;
typedef outer<T> base;
};
};
Then you can obtain 'T' from:
template<class U> class tmpl {
public:
tmpl() { ... /* Can get 'T' from 'typename U::type' */ }
};
If you have further questions, the best place for the discussion is in
the comp.std.c++ newsgroup.