I know that typename
and class
keywords are interchangeable in template arguments, but I thought only typename
is allowed for nested classes specification.
Once I've accidentally wrote incorrectly "class
" instead of "typename
" for a nested class.
And I found is that gcc accepts class
there too, so you can write something like:
class std::vector<T>::iterator it;
instead of
typename std::vector<T>::iterator it;
in your template.
Is this a gcc bug or does the standard really allow this syntax?
UPDATE: example of code:
template <typename T>
void test()
{
class std::vector<T>::iterator it;
}
The __attribute__ directive is used to decorate a code declaration in C, C++ and Objective-C programming languages. This gives the declared code additional attributes that would help the compiler incorporate optimizations or elicit useful warnings to the consumer of that code.
GCC Attributes are used to add various annotations to code outside of the basic source language that assist the compiler. There is also a user attribute that is not interpreted by the compiler but can be used by plugins and static analyses.
Attributes allow us to tell the compiler some specific details about how to compile certain parts of code. These attributes can be applied to variables, structures, structure members and functions. Unfortunately, attributes are a feature of the compiler; they are not part of the C standard language.
It is an area of memory which stores the attributes of a variable in an implementation.
class a::b
is an elaborated type specifier. Name lookup for an elaborated type specifier ignores non-type names. So if you are parsing a template, you can assume two things:
b
, either name lookup gives us a type, or it errors out (wouldn't find any name). In C++0x for that reason, class a::b
doesn't need typename
(you can't put it anywhere anyway on a elaborated type specifier). C++03 doesn't allow that, so GCC appears to implement the C++0x rules as an extension.
That's not particularly bad. Every real compiler implements rules that are sensible and easy to implement in their C++03 version, on their behalf, even if formally they would need to reject it. However, class a::b
must lookup to a class name. If it's merely a typedef, then the lookup for the elaborated type specifier is invalid.
Note that class a::b
is the only way to ignore non-type names in a lookup (except for arcane cases like before a ::
in a qualified name that have similar special rules). For example
template<typename T>
struct A { typename T::type t; }
struct B { class type { }; int type; };
// invalid, even though GCC accepts that incorrectly
A<B> a;
If you compile to C++0x, and you use class T::type t;
, then the code becomes valid, because class T::type
ignores the data member, but finds the nested class.
Section 14.6 ("Name resolution") in ISO 14886:2003 seems to be the definition of how this is supposed to work. Paragraph 3 says:
A qualified-id that refers to a type and in which the nested-name-specifier depends on a template-parameter (14.6.2) shall be prefixed by the keyword
typename
to indicate that the qualified-id denotes a type, forming an elaborated-type-specifier (7.1.5.3).
No mention of the class
keyword. I think this is a GCC bug.
It fails to compile with Comeau Online (Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09)), so at least one of the two compiler has a bug.
error: typedef "iterator" may not be used in an elaborated
type specifier
class std::vector<T>::iterator it;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With