 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Dave B Guest
|
Posted: Sat Sep 25, 2004 10:24 am Post subject: template template parameters using templatized nested classe |
|
|
template template parameters using templatized nested classes
I'm getting a bunch of different results from multiple compilers when
using (or rather attempting to use) a templatized nested class (of a
templatized outer class) as a default template template parameter.
The following are some brief examples of the problems I've been
encountering. The questions I'm hoping to have answered are: What is
the proper way to accomplish what is implied in the following examples?
What (if any) is the Standard's response? And in regards to the
Standard, which compiler is doing it right?
A quick note... you'll notice that I'm using ver 2.95 of the GCC
compiler in my examples. I'm sure some of these issues would be solved
with a newer version. However, I can't use a newer version due to the
limitations of the project I'm on (Playstation 2 development). I would
be curious to see how newer versions of the GCC compiler would handle
it.
EXAMPLE 1
---------
/**
* This structure will be referenced in each example...I'm
* just listing it once for brevity.
*/
template <typename T1, typename T2>
struct Outer {
template <typename T3>
struct Inner { };
};
template
<
typename T1,
typename T2,
template
class TCls = Outer<int, int>::Inner // notice explicit
template parameters <int, int>
| Quote: |
struct MyTest : public TCls<T1> { }; |
//////////////////// Results ////////////////////////
gcc 2.95 - Internal compiler error
Intel 8.0 - Success
MSVC 7.1 - Success
MSVC 8.0 Beta - Success
////////////////////////////////////////////////////
EXAMPLE 2
---------
If I define the default template template parameter to be the
inner class of an outer templatized class defined using template
parameters previously declared in the template argument list...
template
<
typename T1,
typename T2,
template
class TCls = Outer<T1, T2>::Inner // notice use of template
argments <T1, T2>
| Quote: |
struct MyTest : public TCls<T1> { }; |
//////////////////// Results ////////////////////////
gcc 2.95 - Internal compiler error
Intel 8.0 - error: nontype "Outer<T1, T2>::Inner [with T1=T1, T2=T2]"
is not a class template
MSVC 7.1 - error C3202: 'Inner' : invalid default argment for template
parameter '<Unknown>', expected a class template
MSVC 8.0 Beta - Same as 7.1
/////////////////////////////////////////////////////
EXAMPLE 3
---------
However, the following works without a problem (well, except for
gcc)...
template
<
typename T1,
typename T2
| Quote: |
struct MyTest : public Outer |
indirect use of template template parameter as base class
//////////////////// Results ////////////////////////
gcc 2.95 - Internal compiler error
Intel 8.0 - Success
MSVC 7.1 - Success
MSVC 8.0 Beta - Success
/////////////////////////////////////////////////////
EXAMPLE 4
---------
I read in a usenet post somewhere that using the 'template' keyword
when using a templatized dependent name (like the templatized nested
class) can help remedy the problem. The use of 'template' is similar
to 'typename' (when specifying that a dependent name is a type) in that
you are telling the compiler that the dependent name is a template.
So, I tried...
template
<
typename T1,
typename T2,
template
class TCls = Outer<T1, T2>::template Inner // notice the
'template' keyword qualifying 'Inner'
| Quote: |
struct MyTest : public TCls<T1> { }; |
//////////////////// Results ////////////////////////
gcc 2.95 - Internal compiler error
Intel 8.0 - Success
MSVC 7.1 - 'Inner' : invalid default argument for template parameter
'<Unknown>', expected a class template.
MSVC 8.0 Beta - Same as 7.1
/////////////////////////////////////////////////////
EXAMPLE 5
---------
So, it seems that the MSVC compiler doesn't like (or just ignores) the
use of 'template' as indicated above. But, the following works fine
(similar to Example 3 above)...
template
<
typename T1,
typename T2
| Quote: |
struct MyTest : public Outer |
//////////////////// Results ////////////////////////
gcc 2.95 - Success (Even GCC gets it right!)
Intel 8.0 - Success
MSVC 7.1 - Success
MSVC 8.0 Beta - Success
//////////////////////////////////////////////////////
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Glen Low Guest
|
Posted: Sun Sep 26, 2004 9:53 am Post subject: Re: template template parameters using templatized nested cl |
|
|
| Quote: | I'm getting a bunch of different results from multiple compilers when
using (or rather attempting to use) a templatized nested class (of a
templatized outer class) as a default template template parameter.
|
I too have had similar difficulties with the use of template template
parameters. gcc seems to be the best so far, even in places which
require the "template" keyword to signify a template member. xlc++
seems a little more conformant, and Metrowerks tends to react poorly
to partial specializations involving nested templates.
| Quote: | The following are some brief examples of the problems I've been
encountering. The questions I'm hoping to have answered are: What is
the proper way to accomplish what is implied in the following examples?
What (if any) is the Standard's response? And in regards to the
Standard, which compiler is doing it right?
|
I'll only comment on your use of the "template" keyword, see 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 (temp.dep), the member template name
must be prefixed by the keyword template. Otherwise the name is
assumed to name a non-template.
i.e. some expression of the sort a.b or a->b or a::b, that depends on
a template parameter, must be expressed as a. template b or
a->template b or a::template b.
I'd personally stay away from template template params that are nested
templates because of these problems. A better solution might be to use
a template type parameter instead, and use the nested template within
that.
Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Mon Sep 27, 2004 9:08 pm Post subject: Re: template template parameters using templatized nested cl |
|
|
I completely agree with Glen.
| Quote: | I'd personally stay away from template template params that are nested
templates because of these problems. A better solution might be to use
a template type parameter instead, and use the nested template within
that.
|
.....or even going all the way to bottom, as in:
template
<
typename T1,
typename T2,
class Base = typename Outer
| Quote: |
struct MyTest : public Base { }; |
The only good reason to use the template parameter is if you need to
instantiate the template with a different type in the implementation of
MyTest. You could still obtain that using a rebind hack like
std::allocator does. Although less elegant, it should compile like a
charm even on PS2... ;-)
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave B Guest
|
Posted: Tue Sep 28, 2004 10:19 am Post subject: Re: template template parameters using templatized nested cl |
|
|
| Quote: | The only good reason to use the template parameter is if you need to
instantiate the template with a different type in the implementation
of
MyTest.
|
Unfortunately, that's exactly what I need it for...although the example
I posted doesn't reflect that need (I just used it as a simple test
case).
| Quote: | You could still obtain that using a rebind hack like
std::allocator does.
|
I will look into the rebind hack (I actually considered it as an option
before) as you recommend.
Upon further investigation, I've concluded that the proper usage as
supported by the Standard is indeed:
template <
typename T1,
typename T2,
template
| Quote: |
struct MyTest : public TCls<T1> { }; |
The sections of interest are:
Section 14.1.9 - "A default template-argument may be specified for any
kind of template-parameter (type, non-type, template)."
The TCls parameter above is a template template-parameter. It can have
a default template-argument.
Section 14.1.13 - "The scope of a template-parameter extends from its
point of declaration until the end of its template. In particular, a
template-parameter can be used in the declaration of subsequent
template-parameters and their default arguments."
Template parameters T1 and T2 were declared prior to using them in the
declaration of the default template-argument.
Section 14.2.4 (Thanks Glen!) - "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
qualifie-id explicitly depends on a template-parameter, the member
template name must be prefixed by the keyword template. Otherwise the
name is assumed to name a non-template."
The template keyword is needed to prefix 'Inner' as it is a dependent
member template of Outer.
I've submitted a report with the Visual Studio team to inform them that
their compilers (8.0 Beta and 7.1...haven't checked other versions) are
not compliant in this respect.
As for GCC ver. 2.95 for Playstation 2... well, I switched to the SN
Systems PS2 Compiler instead. Everything compiled fine!
I appreciate everyones help.
-Dave
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Glen Low Guest
|
Posted: Wed Sep 29, 2004 9:40 am Post subject: Re: template template parameters using templatized nested cl |
|
|
| Quote: | Upon further investigation, I've concluded that the proper usage as
supported by the Standard is indeed:
template
typename T1,
typename T2,
template <typename> class TCls = Outer<T1, T2>::template Inner
struct MyTest : public TCls<T1> { };
Section 14.2.4 (Thanks Glen!) - "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
qualifie-id explicitly depends on a template-parameter, the member
template name must be prefixed by the keyword template. Otherwise the
name is assumed to name a non-template."
The template keyword is needed to prefix 'Inner' as it is a dependent
member template of Outer.
|
Not so fast, Dave. The section says "when the name of a member
template specialization" but Inner by itself is not a specialization.
Therefore I think it should be
template <typename> class TCls = Outer <T1, T2>::Inner
Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|