Topic: template template parameters and base class names
Author: rogero@howzatt.demon.co.uk
Date: Mon, 30 Apr 2007 18:00:34 CST Raw View
The following code fails to compile on comeau and MSVC 8, but compiles
with g++ 4.0.2
The problem seems to be an ambiguity over the symbol 'Policy1' as a
template template parameter for the variable declaration of 'fails' --
the failing compilers appear to see the name as reference to the base
class.
Should the code compile? I am uncertain.
8X------------------------
class Normal {};
template <class TypeImpl>
class Policy1
{};
template <class> class Templ {};
template <template <class> class Policy>
class TemplTempl
{};
class Derived1 : public Normal
{
Normal works;
Templ<Normal> works_too;
};
class Derived2 : public Policy1<char>
{
Policy1<int> works;
TemplTempl<Policy1> fails; // << !!
TemplTempl<::Policy1> works_too;
};
8X------------------------
"ComeauTest.c": error: type
"Policy1<TypeImpl>::Policy1 [with TypeImpl=char]" is not a
class
template
TT<Policy1> fails;
^
MSVC 8.0: error C3200: 'Policy1<TypeImpl>' : invalid template argument
for
template parameter 'Policy', expected a class template
with
[
TypeImpl=char
]
Roger Orr
MVP in C++ at www.brainbench.com
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 1 May 2007 17:31:11 GMT Raw View
rogero@howzatt.demon.co.uk ha scritto:
> The following code fails to compile on comeau and MSVC 8, but compiles
> with g++ 4.0.2
>
> The problem seems to be an ambiguity over the symbol 'Policy1' as a
> template template parameter for the variable declaration of 'fails' --
> the failing compilers appear to see the name as reference to the base
> class.
>
> Should the code compile? I am uncertain.
It should not compile. Inside class Derived2, the unqualified name
Policy1 not followed by a "<" refers to the injected-class-name of the
base Policy1<char> and not to the class template Policy1 (14.6.1).
> TemplTempl<::Policy1> works_too;
Are you sure? It shouldn't work either, although the reason is
completely different. That's because "<:" is the digraph for "[" so the
line should be interpreted as:
TemplTempl[:Policy1> works_too;
which, of course, is a syntax error. This is the correct way to write
the line:
TemplTempl< ::Policy1> works_too;
^ a white space here!!!
HTH,
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.comeaucomputing.com/csc/faq.html ]
Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Tue, 1 May 2007 12:31:58 CST Raw View
On 1 Mai, 02:00, rog...@howzatt.demon.co.uk wrote:
> Should the code compile? I am uncertain.
No, the code should not compile, explanations v.i.
> 8X------------------------
> class Normal {};
>
> template <class TypeImpl>
> class Policy1
> {};
>
> template <class> class Templ {};
>
> template <template <class> class Policy>
> class TemplTempl
> {};
>
> class Derived1 : public Normal
> {
> Normal works;
> Templ<Normal> works_too;
>
> };
>
> class Derived2 : public Policy1<char>
> {
> Policy1<int> works;
> TemplTempl<Policy1> fails; // << !!
This should not compile, because according to
14.6.1/1 Policy1 is an injected-class-name that
is equivalent to the injected-class-name
Policy1<char> (in this situation). Due to this
"expansion" it's understandable that
TemplTempl<Policy1> fails;
essentially means
TemplTempl<Policy1<char> > fails;
which would cause the same compile error
you observe.
The above interpretation is effectively disabled by
using a qualified name, see e.g. para 2c,
"When the normal name of the template (i.e., the name
from the enclosing scope, not the injected-classname)
is used without a template-argument-list, it refers to the
class template itself and not a specialization of the
template."
and therefore
TemplTempl< ::Policy1> works_too;
compiles.
> TemplTempl<::Policy1> works_too;};
This should *not* compile, because <: is
a so-called alternative token (corresponding to
'[') which would lead to the (invalid) C++ code
interpretation of
TemplTempl[:Policy1> works_too;
Since you argue that it compiled, you probably
have actually tested
TemplTempl< ::Policy1> works_too;
where the space between < and : is required.
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Pierre Barbier de Reuille <pierre.barbierdereuille@gmail.com>
Date: Fri, 4 May 2007 11:51:39 CST Raw View
On 30 avr, 18:00, rog...@howzatt.demon.co.uk wrote:
[...]
>
Given the template is used fully instantiated, it should be just
considered as any other class with its full name. Thus this code
should compile just fine ! I checked the standard for that, and I
didn't find any special handling of template when inheriting a fully
instanciated one.
Even worse, how would these compiler behave with:
class Derived3 : public Policy1<char>, public Policy1<int>
{
Policy1 a; // Which one is supposed to be used here ???
};
definitely, the compiler should not assume in that case that Policy1
has any default argument because you inherit it !
Pierre
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 7 May 2007 13:04:25 CST Raw View
[To the mods: This is my second trial after several days.
I hope it comes through...]
On 4 Mai, 19:51, Pierre Barbier de Reuille
<pierre.barbierdereui...@gmail.com> wrote:
> Given the template is used fully instantiated, it should be just
> considered as any other class with its full name. Thus this code
> should compile just fine ! I checked the standard for that, and I
> didn't find any special handling of template when inheriting a fully
> instanciated one.
According to 14.6.1/1 we speak about the injected-class-name
here, which is a concept that applies even for non-template
classes. This paragraph also says:
"[..] When it is used with a template-argument-list, it refers to
the specified class template specialization, which could be
the current specialization or another specialization."
this is emphasized by 14.6.1/2:
"Within the scope of a class template specialization or partial
specialization, when the injected-class-name is not followed
by a <, it is equivalent to the injected-class-name followed by
the template-arguments of the class template specialization
or partial specialization enclosed in <>."
Now 14.7/4 clarifies that we have indeed a specialization here:
"An instantiated template specialization can be either implicitly
instantiated (14.7.1) for a given argument list or be explicitly
instantiated (14.7.2). A specialization is a class, function, or
class member that is either instantiated or explicitly specialized
(14.7.3)."
And the scope rule explained in 14.6.1/2a allows this
template-as-base-class situation we are discussing
here.
> Even worse, how would these compiler behave with:
>
> class Derived3 : public Policy1<char>, public Policy1<int>
> {
> Policy1 a; // Which one is supposed to be used here ???
>
> };
>
> definitely, the compiler should not assume in that case that Policy1
> has any default argument because you inherit it !
We have no "default argument" here and indeed Derived3
should not compile as currently written. This special
situation of a multi-base-class is also described by the
standard, namely by 14.6.1/2b:
"A lookup that finds an injected-class-name (10.2) can
result in an ambiguity in certain cases (for example, if
it is found in more than one base class). If all of the
injected-class-names that are found refer to specializations
of the same class template, and if the name is followed
by a template-argument-list, the reference refers to the
class template itself and not a specialization thereof,
and is not ambiguous."
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 8 May 2007 02:13:14 GMT Raw View
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D MODERATOR'S COMMENT:=20
Apologies for the delay in moderation; this appears to be caused
by my ISP (Cox) dropping and/or blocking e-mail.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D END OF MODERATOR'S COMMENT
Pierre Barbier de Reuille ha scritto:
> On 30 avr, 18:00, rog...@howzatt.demon.co.uk wrote:
> [...]
>=20
> Given the template is used fully instantiated, it should be just
> considered as any other class with its full name. Thus this code
> should compile just fine ! I checked the standard for that, and I
> didn't find any special handling of template when inheriting a fully
> instanciated one.
You have definitely missed 14.6.1/1: "Like normal (non-template)
classes, class templates have an injected-class-name (clause 9). The
injected class-name can be used with or without a
template-argument-list. When it is used without a template
argument-list, it is equivalent to the injected-class-name followed by
the template-parameters of the class template enclosed in <>. [...]"
So there *is* a special handling when inheriting templates. See my other
post and Daniel Kr=FCgler's for details.
>=20
> Even worse, how would these compiler behave with:
>=20
> class Derived3 : public Policy1<char>, public Policy1<int>
> {
> Policy1 a; // Which one is supposed to be used here ???
> };
In this case Policy1 would refer to *both* Policy<char> and Policy1<int>
and therefore cannot be used because it would be ambiguous.
>=20
> definitely, the compiler should not assume in that case that Policy1
> has any default argument because you inherit it !
I really don't understand what you mean... Anyway, it seems that you
completely off-track to me. The compiler does not *assume* anything.
What is happening in the OP's code is this:
1) by clause 9: the name "Policy1<char>" is injected in the class scope
of Policy1<char>
2) by 14.6.1/1: the name "Policy1" is also injected in the class scope
of Policy1<char> as a synonym to "Policy1<char>".
3) class Derived2, by inheriting from Policy<char>, inherits both
injected names
When you inherit from both Policy1<char> and Policy1<int>, the name
"Policy1" is injected twice with two different meanings in the scope of
each base class. In the scope of class Derived2, which would inherit
both names, that makes the name ambiguous and unusable.
HTH,
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.comeaucomputing.com/csc/faq.html ]
Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 7 May 2007 21:11:28 CST Raw View
===================================== MODERATOR'S COMMENT:
Apologies for the delay in moderation; this appears to be caused
by my ISP (Cox) dropping and/or blocking e-mail.
===================================== END OF MODERATOR'S COMMENT
On 4 Mai, 19:51, Pierre Barbier de Reuille
<pierre.barbierdereui...@gmail.com> wrote:
> Given the template is used fully instantiated, it should be just
> considered as any other class with its full name. Thus this code
> should compile just fine ! I checked the standard for that, and I
> didn't find any special handling of template when inheriting a fully
> instanciated one.
According to 14.6.1/1 we speak about the injected-class-name
here, which is a concept that applies even for non-template
classes. This paragraph also says:
"[..] When it is used with a template-argument-list, it refers to
the specified class template specialization, which could be
the current specialization or another specialization."
this is emphasized by 14.6.1/2:
"Within the scope of a class template specialization or partial
specialization, when the injected-class-name is not followed
by a <, it is equivalent to the injected-class-name followed by
the template-arguments of the class template specialization
or partial specialization enclosed in <>."
Now 14.7/4 clarifies that we have indeed a specialization here:
"An instantiated template specialization can be either implicitly
instantiated (14.7.1) for a given argument list or be explicitly
instantiated (14.7.2). A specialization is a class, function, or
class member that is either instantiated or explicitly specialized
(14.7.3)."
And the scope rule explained in 14.6.1/2a allows this
template-as-base-class situation we are discussing
here.
> Even worse, how would these compiler behave with:
>
> class Derived3 : public Policy1<char>, public Policy1<int>
> {
> Policy1 a; // Which one is supposed to be used here ???
>
> };
>
> definitely, the compiler should not assume in that case that Policy1
> has any default argument because you inherit it !
We have no "default argument" here and indeed Derived3
should not compile as currently written. This special
situation of a multi-base-class is also described by the
standard, namely by 14.6.1/2b:
"A lookup that finds an injected-class-name (10.2) can
result in an ambiguity in certain cases (for example, if
it is found in more than one base class). If all of the
injected-class-names that are found refer to specializations
of the same class template, and if the name is followed
by a template-argument-list, the reference refers to the
class template itself and not a specialization thereof,
and is not ambiguous."
Greetings from Bremen,
Daniel Kr gler
---
[ 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.comeaucomputing.com/csc/faq.html ]