Стандарт C++ 98 (1119566), страница 39
Текст из файла (страница 39)
};SS;ST;// error127ISO/IEC 14882:1998(E)© ISO/IEC8 Declarators8 Declaratorscv-qualifier-seq:cv-qualifier cv-qualifier-seqoptcv-qualifier:constvolatiledeclarator-id:id-expression::opt nested-name-specifieropt type-nameA class-name has special meaning in a declaration of the class of that name and when qualified by thatname using the scope resolution operator :: (5.1, 12.1, 12.4).8.1 Type names1[dcl.name]To specify type conversions explicitly, and as an argument of sizeof, new, or typeid, the name of atype shall be specified. This can be done with a type-id, which is syntactically a declaration for an object orfunction of that type that omits the name of the object or function.type-id:type-specifier-seq abstract-declaratoropttype-specifier-seq:type-specifier type-specifier-seqoptabstract-declarator:ptr-operator abstract-declaratoroptdirect-abstract-declaratordirect-abstract-declarator:direct-abstract-declaratoropt( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationoptdirect-abstract-declaratoropt [ constant-expressionopt ]( abstract-declarator )It is possible to identify uniquely the location in the abstract-declarator where the identifier would appearif the construction were a declarator in a declaration.
The named type is then the same as the type of thehypothetical identifier. [Example:intintintintintint**[3](*)[3]*()(*)(double)// int i// int *pi// int *p[3]// int (*p3i)[3]// int *f()// int (*pf)(double)name respectively the types “int,” “pointer to int,” “array of 3 pointers to int,” “pointer to array of 3int,” “function of (no parameters) returning pointer to int,” and “pointer to a function of (double)returning int.’’ ]2A type can also be named (often more easily) by using a typedef (7.1.3).8.2 Ambiguity resolution1[dcl.ambig.res]The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8can also occur in the context of a declaration.
In that context, the choice is between a function declarationwith a redundant set of parentheses around a parameter name and an object declaration with a function-stylecast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant128© ISO/IECISO/IEC 14882:1998(E)8 Declarators8.2 Ambiguity resolutionparentheses around the parameter name.
] [Example:struct S {S(int);};void foo(double a){S w(int(a));S x(int());S y((int)a);S z = int(a);}// function declaration// function declaration// object declaration// object declaration—end example]2The ambiguity arising from the similarity between a function-style cast and a type-id can occur in differentcontexts. The ambiguity appears as a choice between a function-style cast expression and a declaration of atype. The resolution is that any construct that could possibly be a type-id in its syntactic context shall beconsidered a type-id.3[Example:#include <cstddef>char *p;void *operator new(size_t, int);void foo() {const int x = 63;new (int(*p)) int;// new-placement expressionnew (int(*[x]));// new type-id}4For another example,template <class T>struct S {T *p;};S<int()> x;S<int(1)> y;5For another example,void foo(){sizeof(int(1));sizeof(int());}6// type-id// expression (ill-formed)// expression// type-id (ill-formed)For another example,void foo(){(int(1));(int())1;}// expression// type-id (ill-formed)—end example]7Another ambiguity arises in a parameter-declaration-clause of a function declaration, or in a type-id that isthe operand of a sizeof or typeid operator, when a type-name is nested in parentheses.
In this case, thechoice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id. The resolution is to consider the type-name as asimple-type-specifier rather than a declarator-id. [Example:129ISO/IEC 14882:1998(E)© ISO/IEC8.2 Ambiguity resolutionclass C { };void f(int(C)) { }8 Declarators// void f(int (*fp)(C c)) { }// not: void f(int C);int g(C);void foo() {f(1);f(g);}// error: cannot convert 1 to function pointer// OKFor another example,class C { };void h(int *(C[10]));// void h(int *(*_fp)(C _parm[10]));// not: void h(int *C[10]);—end example]8.3 Meaning of declarators1[dcl.meaning]A list of declarators appears after an optional (clause 7) decl-specifier-seq (7.1).
Each declarator containsexactly one declarator-id; it names the identifier that is declared. The id-expression of a declarator-id shallbe a simple identifier except for the declaration of some special functions (12.3, 12.4, 13.5) and for the declaration of template specializations or partial specializations (14.7). A declarator-id shall not be qualifiedexcept for the definition of a member function (9.3) or static data member (9.4) or nested class (9.7) outsideof its class, the definition or explicit instantiation of a function, variable or class member of a namespaceoutside of its namespace, or the definition of a previously declared explicit specialization outside of itsnamespace, or the declaration of a friend function that is a member of another class or namespace (11.4).When the declarator-id is qualified, the declaration shall refer to a previously declared member of the classor namespace to which the qualifier refers, and the member shall not have been introduced by a usingdeclaration in the scope of the class or namespace nominated by the nested-name-specifier of thedeclarator-id.
[Note: if the qualifier is the global :: scope resolution operator, the declarator-id refers to aname declared in the global namespace scope. ] In the qualified declarator-id for a class or namespacemember definition that appears outside of the member’s class or namespace, the nested-name-specifier shallnot name any of the namespaces that enclose the member’s definition. [Example:namespace A {struct B {void f();};void A::B::f() { }// ill-formed: the declarator must not be// qualified with A::}—end example]2An auto, static, extern, register, mutable, friend, inline, virtual, or typedef specifier applies directly to each declarator-id in a init-declarator-list; the type specified for each declarator-iddepends on both the decl-specifier-seq and its declarator.3Thus, a declaration of a particular identifier has the formT Dwhere T is a decl-specifier-seq and D is a declarator.
Following is a recursive procedure for determining thetype specified for the contained declarator-id by such a declaration.4First, the decl-specifier-seq determines a type. In a declarationT Dthe decl-specifier-seq T determines the type “T.” [Example: in the declaration130© ISO/IECISO/IEC 14882:1998(E)8 Declarators8.3 Meaning of declaratorsint unsigned i;the type specifiers int unsigned determine the type “unsigned int” (7.1.5.2). ]5In a declaration T D where D is an unadorned identifier the type of this identifier is “T.”6In a declaration T D where D has the form( D1 )the type of the contained declarator-id is the same as that of the contained declarator-id in the declarationT D1Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complexdeclarators.8.3.1 Pointers1[dcl.ptr]In a declaration T D where D has the form* cv-qualifier-seqopt D1and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T,” then the type of theidentifier of D is “derived-declarator-type-list cv-qualifier-seq pointer to T.” The cv-qualifiers apply to thepointer and not to the object pointed to.2[Example: the declarationsconst int ci = 10, *pc = &ci, *const cpc = pc, **ppc;int i, *p, *const cp = &i;declare ci, a constant integer; pc, a pointer to a constant integer; cpc, a constant pointer to a constantinteger, ppc, a pointer to a pointer to a constant integer; i, an integer; p, a pointer to integer; and cp, aconstant pointer to integer.
The value of ci, cpc, and cp cannot be changed after initialization. The valueof pc can be changed, and so can the object pointed to by cp. Examples of some correct operations arei = ci;*cp = ci;pc++;pc = cpc;pc = p;ppc = &pc;Examples of ill-formed operations areci = 1;ci++;*pc = 2;cp = &ci;cpc++;p = pc;ppc = &p;// error// error// error// error// error// error// errorEach is unacceptable because it would either change the value of an object declared const or allow it to bechanged through a cv-unqualified pointer later, for example:*ppc = &ci;*p = 5;// OK, but would make p point to ci ...// ... because of previous error// clobber ci—end example]3See also 5.17 and 8.5.131ISO/IEC 14882:1998(E)© ISO/IEC8.3.1 Pointers48 Declarators[Note: there are no pointers to references; see 8.3.2.