• No results found

Lexical structure

In document C++ CLI Standard pdf (Page 48-51)

A number of issues are not yet discussed here. Much of this clause is yet to be added. [[#24]]

9.1 Tokens

9.1.1 Identifiers

Certain places in the Standard C++ grammar do not allow identifiers. However, C++/CLI allows a defined 5

set of identifiers to exist in those places, with these identifiers having special meaning. [Note: Such

identifiers are colloquially referred to as context-sensitive keywords; none-the-less, they are identifiers. end note] The identifiers that carry special meaning in certain contexts are:

abstract delegate event finally

generic in initonly literal

10

override property sealed where

When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production. Ensuring that the identifier is meaningful is a semantic check rather than a syntax check.

When the token generic is found, it has special meaning if and only if it is not preceded by the token ::

15

and is followed by the token < and then either of the keywords class or typename. [Note: In rare cases, a

valid Standard C++ program could contain the token sequence generic followed by < followed by class

where generic should be interpreted as a type name. For example: template<typename T> struct generic {

typedef int I; 20 }; class X {}; generic<class X> x1; generic<class X()> x2;

In such cases, use typename to indicate that the occurrence of generic is a type name:

25

typename generic<class X> x1; typename generic<class X()> x2;

or, in these particular cases, an alternative would be to remove the keyword class (that is, to not use the

elaborated-type-specifier), for example:

generic<X> x1;

30

generic<X()> x2;

end note]

The grammar productions for elaborated-type-specifier (C++ Standard §7.1.5.3, §14.6, and §A.6) that mention typename are extended as follows, to make nested-name-specifier optional in the first of the two applicable productions:

35

elaborated-type-specifier: . . .

typename ::opt nested-name-specifieropt identifier

typename ::opt nested-name-specifier templateopt template-id

. . . 40

Lexical structure

"A qualified-ididentifier 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-ididentifier denotes a type, forming an elaborated-type-specifier (7.1.5.3)."

and §14.6/5 is deleted:

"The keyword typename shall only be used in template declarations and definitions, including in the return 5

type of a function template or member function template, in the return type for the definition of a member function of a class template or of a class nested within a class template, and in the type-specifier for the definition of a static member of a class template or of a class nested within a class template. The keyword typename shall be applied only to qualified names, but those names need not be dependent. The keyword typename shall be used only in contexts in which dependent names can be used. This includes template 10

declarations and definitions but excludes explicit specialization declarations and explicit instantiation declarations. The keyword typename is not permitted in a base-specifier or in a mem-initializer; in these contexts a qualified-id that depends on a template-parameter (14.6.2) is implicitly assumed to be a type name."

[Note: The presence of typename lets the programmer disambiguate otherwise ambiguous cases such as the

15

token sequence property :: X x;. The declaration property :: X x; declares a member variable

named x of type property::X, as it does in Standard C++. The token sequence property typename :: X x; declares a property named x of type ::X. end note]

When name lookup for any of array, interior_ptr, pin_ptr, or safe_cast fails to find the name, and

the name is not followed by a left parenthesis, the name is interpreted as though it were qualified with 20

cli:: and the lookup succeeds, finding the name in namespace ::cli.

When name lookup for any of array, interior_ptr, pin_ptr, or safe_cast succeeds and finds the

name in namespace ::cli, the name is not a normal identifier, but has special meaning as described in this

Standard.

9.1.2 Keywords 25

The following keywords are added to those in the C++ Standard (§2.11):

enum░class enum░struct for░each gcnew

interface░class interface░struct nullptr ref░class

ref░struct value░class value░struct

The symbol ░ is used in the grammar to signify that white-space appears within the keyword. Any white- 30

space, including comments and new-lines (but excluding documentation comments and newlines in macros), is permitted in the position signified by the ░ symbol. Following translation phase 4, a keyword with ░ will be a single token. [Note: The ░ symbol is only used in the grammar of the language. Examples will include white-space as is required in a well-formed program. end note] [Note: Keywords that include the ░ symbol can be produced by macros, but are never considered to be macro names. end note]

35

Translation phase 4 in the C++ Standard (§2.1/4) is extended as follows:

Preprocessing directives are executedparsed and stored. Then, in the translation unit and in each macro replacement-list, starting with the first token, each pair of adjacent tokens token1 and token2 is successively considered, and if token1░token2 is a keyword, then token1 and token2 are replaced with the single token token1░token2. and Then macro invocations are expanded. If a character sequence that matches the syntax 40

of a universal-character-name is produced by token concatenation (16.3.3), the behavior is undefined. A

#include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively.

In some places in the grammar, specific identifiers have special meaning, but are not keywords. [Note: For example, within a virtual function declaration, the identifiers abstract and sealed have special meaning.

45

Ordinary user-defined identifiers are never permitted in these locations, so this use does not conflict with a use of these words as identifiers. For a complete list of these special identifiers, see §9.1.1. end note]

9.1.3 Literals

literal:

null-literal 9.1.3.1 The null literal

null-literal:: 5

nullptr

The null-literal is the keyword nullptr, whose type is the null type (§12.3.4). nullptr represents the

null value constant and is unique. This literal is not an lvalue.

The null value constant can be converted to any handle type, with the result being a null handle. The null value constant can also be converted to any pointer type, with the result being a null pointer.

10

9.1.4 Operators and punctuators

It has been agreed that >> will be handled apprpriately to allow constructs such as List<List<int>> to be handled correctly. If a < for a template, for example, is seen, and >> that is not inside parentheses, that >> will always be considered to be the closing delimiter of two < symbols, and results in an error if there are not two such corresponding < symbols. [[Ed.]]

Basic concepts

In document C++ CLI Standard pdf (Page 48-51)