 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Scott Meyers Guest
|
Posted: Sat Jan 29, 2005 6:31 am Post subject: No typename needed before std::list<T>? |
|
|
I thought I understood the rules regarding typename, but it seems I was
mistaken. I was under the impression that anytime you refer to a dependent
type name in a template, you had to qualify it with typename. But consider
this:
template<typename T>
class Widget {
typedef typename std::list<T> CollectionType1; // 1
typedef std::set<T> CollectionType2; // 2
};
My expectation was that 1 would compile, but 2 would not. But the three
compilers I have here all accept both. Sigh. Why doesn't 2 require a
typename?
Thanks,
Scott
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Nicolas Pavlidis Guest
|
Posted: Sat Jan 29, 2005 2:14 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
[email]Usenet (AT) aristeia (DOT) com[/email] (Scott Meyers) writes:
| Quote: | I thought I understood the rules regarding typename, but it seems I was
mistaken. I was under the impression that anytime you refer to a dependent
type name in a template, you had to qualify it with typename. But consider
this:
template<typename T
class Widget {
typedef typename std::list
typedef std::set<T> CollectionType2; // 2
};
|
I always thought that only nested types have to be qualified with
typename:
template<typename Type>
class Test
{
public:
typedef std::list<Type> TypeList; //
typedef typename std::list<Type>::iterator TypeListIterator;
};
If I remove the typename of the second typedef I'll get a warning under
gcc 3.3 and an errormessage under gcc 3.4.
I'm far away from beeing an expert so I have no good explanation for
this, but maybe it's becaue Templatets can be instantiated with
incomplete types, and so the line marked with the smily wokrs, but the
other line does not, because std::list<Type> is no complete type at this
moment, but it can be nonsense too .
Best regards,
Nicolas
--
| Quote: | Nicolas Pavlidis | Elvis Presly: | |__ |
Student of SE & KM | "Into the goto" | |__| |
[email]pavnic (AT) sbox (DOT) tugraz.at[/email] | ICQ #320057056 | |
-------------------University of Technology, Graz----------------|
|
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Michael Pryhodko Guest
|
Posted: Sat Jan 29, 2005 2:14 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
| Quote: | template<typename T
class Widget {
typedef typename std::list
typedef std::set<T> CollectionType2; // 2
};
My expectation was that 1 would compile, but 2 would not. But the
three
compilers I have here all accept both. Sigh. Why doesn't 2 require
a
typename?
|
14.6.p2... read twice (there is barely visible 'OR')
Bye.
Sincerely yours, Michael.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
David B. Held Guest
|
Posted: Sat Jan 29, 2005 4:17 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
Scott Meyers wrote:
| Quote: | I thought I understood the rules regarding typename, but it seems I was
mistaken. I was under the impression that anytime you refer to a dependent
type name in a template, you had to qualify it with typename. But consider
this:
template<typename T
class Widget {
typedef typename std::list
typedef std::set<T> CollectionType2; // 2
};
My expectation was that 1 would compile, but 2 would not. But the three
compilers I have here all accept both. Sigh. Why doesn't 2 require a
typename?
|
Neither of them do. The compiler already knows that std::list is a
parameterized type. Once you supply a parameter (formal or otherwise),
it, becomes a concrete (typedefable) type. You cannot substitute any
value for T to make std::list<T> anything but a type (say, a value).
On the other hand, the same is not true for std::list<T>::iterator.
Suppose, for the sake of argument, that I perversely defined
std::list<T>::iterator like so:
template <typename T>
struct list
{
typedef T* iterator;
};
template <>
struct list<int>
{
static int const iterator = 42;
};
This is not only perfectly confusing, it's perfectly legal. Now,
does std::list<T>::iterator refer to a type or a value? Without
knowing what T is, you can't say, can you? In order to write
template types that assume one way or the other, you have to give
the compiler a hint as to which one you are writing for. That's
why iterator is a dependent type, and that's why it needs a
typename.
Dave
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Bo Persson Guest
|
Posted: Sat Jan 29, 2005 6:00 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
"Scott Meyers" <Usenet (AT) aristeia (DOT) com> skrev i meddelandet
news:MPG.1c64b696d96bc439897b1 (AT) news (DOT) hevanet.com...
| Quote: | I thought I understood the rules regarding typename, but it seems I was
mistaken. I was under the impression that anytime you refer to a
dependent
type name in a template, you had to qualify it with typename. But
consider
this:
template<typename T
class Widget {
typedef typename std::list
typedef std::set<T> CollectionType2; // 2
};
My expectation was that 1 would compile, but 2 would not. But the
three
compilers I have here all accept both. Sigh. Why doesn't 2 require a
typename?
|
Because std::set is known to be a type, for all T's. So is std::list, so
the typename in 1 isn't needed either.
The problem of deciding what is type comes up when the types are nested.
You could have a specialization, like
template<>
class std::set<some_type>
{
int iterator;
};
typedef typename std::set<T>::iterator iterator_type;
Here you really need typename to indicate that you want the typedef to
work for the cases where iterator really *is* a type, and not for the
cases where it might be something else, like a variable.
For typedefs the compiler might be intelligent enough to expect types
anyway, but for an expression like
typename std::set<T>::value_type * x;
it is impossible to determine if it is a pointer declaration or a
multiplication, unless you know what names are supposed to be types.
Bo Persson
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Sat Jan 29, 2005 9:59 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
[email]Usenet (AT) aristeia (DOT) com[/email] (Scott Meyers) writes:
| Quote: | I thought I understood the rules regarding typename, but it seems I was
mistaken. I was under the impression that anytime you refer to a dependent
type name in a template, you had to qualify it with typename. But consider
this:
template<typename T
class Widget {
typedef typename std::list
typedef std::set<T> CollectionType2; // 2
};
My expectation was that 1 would compile, but 2 would not. But the three
compilers I have here all accept both. Sigh. Why doesn't 2 require a
typename?
|
First of all, since I know you have it, check out Appendix B of
http://boost-consulting.com/metaprogramming-book.html. I think we've
got the most complete explanation going right now. It lays out all
the groundwork for understanding this.
The compiler needs typename to help it distinguish when a name refers
to a type. You can't even compile
typedef std::set<T> CollectionType2;
unless the compiler has seen a declaration for std::set<T>, and
nothing you can do with specializations or otherwise will change the
fact that std::set is a class template and std::set<T> is a type.
The reason the compiler needs to see typename in
typedef typename std::set<T>::iterator iterator2;
is twofold: first, you might not have shown it the primary template
definition for std::set; that line should compile even after only
seeing
namespace std {
template <class T, class A> class set;
}
Second, whether std::set<T>::iterator is a type could depend on the
actual T you are passed. For example,
template <class T>
struct set<T*>
{
enum { iterator };
}
Whoops; set<T*>::iterator is not a type.
HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Scott Meyers Guest
|
Posted: Sun Jan 30, 2005 1:44 am Post subject: Re: No typename needed before std::list<T>? |
|
|
On Sat, 29 Jan 2005 21:59:13 GMT, David Abrahams wrote:
It's nice, but it has the disadvantage of defining "dependent name" in a
way I find hard to understand, much less explain. As the author of source
code, how am I to know when the "syntactic role" played by an identifier
depends on what type a type parameter turns out to be? Section 9.3.2 of
Vandevoorde and Josuttis is more precise, but it requires that I understand
what a qualified name is, and I find that hard to do, even though they do
their best to define it in table 9.2. Further complicating matters is the
Standard, which, as is often the case regarding templates, is essentially
impossible to understand. IMO.
Anyway, I do understand why typename is needed to disambiguate the meaning
of nested typedefs in dependent type names (e.g, Foo<T>::Widget). And I
guess I understand that compilers can tell whether Foo<T> is a type for any
template Foo and type T, so there's no need for typename in that case.
I still think it would be easier to understand and explain if the rule were
that all dependent type names must be preceded by typename, but I now
understand that that's not the rule, and I thank everybody who contributed
to my new understanding of the situation.
Scott
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Mon Jan 31, 2005 2:07 am Post subject: Re: No typename needed before std::list<T>? |
|
|
Scott Meyers wrote:
[...]
| Quote: | I still think it would be easier to understand and explain if the
rule were
that all dependent type names must be preceded by typename, but I now
understand that that's not the rule, and I thank everybody who
contributed
to my new understanding of the situation.
|
I think I agree the "rules" are a bit too complicated right now.
More precisely, I think it's okay for the rules to be complicated,
but you should be able to get away with a simple "rule of thumb"
(which may not be optimal in terms of amount of source code,
but which doesn't requiring "trying out the various combinations
until the compiler eats it").
The Core Working Group has been working both on allowing the
"typename" disambiguator in more places, and on requiring it in
fewer places (both of those are good trends IMO).
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
};
(Sorry, I cannot resist ;-)
Daveed
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Mon Jan 31, 2005 2:07 am Post subject: Re: No typename needed before std::list<T>? |
|
|
[email]Usenet (AT) aristeia (DOT) com[/email] (Scott Meyers) writes:
| Quote: | On Sat, 29 Jan 2005 21:59:13 GMT, David Abrahams wrote:
First of all, since I know you have it, check out Appendix B of
http://boost-consulting.com/metaprogramming-book.html. I think we've
got the most complete explanation going right now. It lays out all
the groundwork for understanding this.
It's nice, but it has the disadvantage of defining "dependent name" in a
way I find hard to understand, much less explain. As the author of source
code, how am I to know when the "syntactic role" played by an identifier
depends on what type a type parameter turns out to be?
|
That description is not meant to be a definition; it's designed to
give "a feel" for what's going on. The precise rules are in section
B.2.
| Quote: | Section 9.3.2 of Vandevoorde and Josuttis is more precise
|
Did you stop reading before you got to Section B.2?
--
Dave Abrahams
Boost Consulting
www.boost-consulting.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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Gianni Mariani Guest
|
Posted: Mon Jan 31, 2005 6:25 am Post subject: Re: No typename needed before std::list<T>? |
|
|
[email]google (AT) vandevoorde (DOT) com[/email] wrote:
....
| Quote: |
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
};
|
Are you sure ?
gcc (GCC) 4.0.0 20050102 (experimental) says:
typename_nonsense.cpp:11: error: expected ‘;’ before ‘i’
typename_nonsense.cpp:12: error: expected ‘;’ before ‘c’
typename_nonsense.cpp:13: error: expected ‘;’ before ‘l’
Similar errors from MSVC++ 2003.
Although http://www.comeaucomputing.com/tryitout does seem to agree with
you.
g++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) also seems to agree
with you.
What a mess...
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Mon Jan 31, 2005 6:22 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
Gianni Mariani wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
...
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
|
Presumably most compilers will treat at least S<T> as dependent,
whereas S<T> and S should logically be treated as locally declared and
therefore non-dependent?
| Quote: | };
Are you sure ?
gcc (GCC) 4.0.0 20050102 (experimental) says:
typename_nonsense.cpp:11: error: expected ?;? before ?i?
typename_nonsense.cpp:12: error: expected ?;? before ?c?
typename_nonsense.cpp:13: error: expected ?;? before ?l?
Similar errors from MSVC++ 2003.
|
This is not terribly surprising, as I think the code is ill-formed
according to the current standard. But see
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#224>.
Given that David works on the front-end used by the Comeau compiler,
that's not surprising.
| Quote: | g++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) also seems to agree
with you.
|
It doesn't implement two-phase name resolution.
--
Ben Hutchings
Larkinson's Law: All laws are basically false.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Mon Jan 31, 2005 6:23 pm Post subject: Re: No typename needed before std::list<T>? |
|
|
Gianni Mariani wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
...
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
};
Are you sure ?
|
Yes. It's a consequence of the resolution of core issue 224
(which improves the definition of "dependent type").
Daveed
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Jonathan Turkanis Guest
|
Posted: Tue Feb 01, 2005 3:18 am Post subject: Re: No typename needed before std::list<T>? |
|
|
Gianni Mariani wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
};
Are you sure ?
Although http://www.comeaucomputing.com/tryitout does seem to agree
with you.
|
I 'm not sure this is entirely a coincidence ;-)
Jonathan
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
msalters Guest
|
Posted: Tue Feb 01, 2005 3:18 am Post subject: Re: No typename needed before std::list<T>? |
|
|
Gianni Mariani wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
...
Oh, and here is another "interesting" illustration of the current
rules; this is a test for the compiler's understanding of so-called
"injected class names":
struct N {
typedef char C;
};
template<typename> struct B {
typedef long L;
};
template<typename T> struct S: N, B<T> {
typedef int I;
S<T>::I i; // Okay
S<T>::C c; // Okay
S::L l; // Error: typename required
};
Are you sure ?
gcc (GCC) 4.0.0 20050102 (experimental) says:
typename_nonsense.cpp:11: error: expected ';' before 'i'
typename_nonsense.cpp:12: error: expected ';' before 'c'
typename_nonsense.cpp:13: error: expected ';' before 'l'
Similar errors from MSVC++ 2003.
Although http://www.comeaucomputing.com/tryitout does seem to agree
with
you.
|
If you know how Comeau works, and where Daveed works, that's not a
very big surprise ;)
| Quote: | g++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) also seems to agree
with you.
What a mess...
|
Yep. It's complicated.
/Without/ looking at the standard, I'd say the difference is that
S names both a class and a template inside the definition of S. The
form S<T>::I refers to the current class, but the explicit use of T
defers name lookup to instantiation.
In the form S::L, the name L is not looked up in a base class during
the first phase, yet without lookup it's not known whether it names
a type.
i.e. the typename rules differ between the two phases of name lookup
in templates.
Looking at WP1655 (draft standard),
the relevant wording does appear to be similar:
S is indeed "injected" (9) which means it names both the class and
the template (which is why you can write both S and S<T>). However,
they are equivalent.
However, the injected name (S) is just as dependent as the form
S<T> (which is obviously dependent). Both name the "current
instantiation". Hence, S::C and S<T>::C are also equivalent
( but S::I is not equivalent with S::L).
14.6/3 explains when typename is required: "A qualified-id that
refers to a type and in which the nested-name-specifier depends
on a template-parameter (14.6.2) but does not refer to a member
of the current instantiation (14.6.2.1) shall be prefixed by
the keyword typename"
Now, both S::I and S::L are qualified-id's which do depend on
<T>. So, is there anything special about the "member of the
current instantiation" term? It's defined in 14.6.2.1. Both
S::I and S::L are members of the current instantiation (and
so is S::X, even though there's no X in S - yet).
So, in the current draft neither form requires typename. I'd
expect gcc 4 to follow the current draft.
HTH,
Michiel Salters
NB. "Unqualified name" is a rather important term, but it's not
formally defined. Is this a Defect? Or is it just any name that's
not a qualified name? That leaves us with the question, what's
a "Qualified name"? Obviously, there's a close relation to
qualified-id's and unqualified-id's, as defined in 5.1
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Scott Meyers Guest
|
Posted: Tue Feb 01, 2005 4:42 am Post subject: Re: No typename needed before std::list<T>? |
|
|
On Mon, 31 Jan 2005 02:07:44 GMT, David Abrahams wrote:
| Quote: | Did you stop reading before you got to Section B.2?
|
Actually, yes. You guys moved on to a new topic ("Problem Two"), so I
thought you were done with the old topic ("Problem One"). Silly somebody.
Maybe me. Maybe you. Maybe both of us. I'm not sure. Anyway, B.2 does
offer a much more detailed blow by blow of the situation.
Scott
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
|
|
| 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
|
|