Стандарт C++ 11 (1119564), страница 56
Текст из файла (страница 56)
That isT D1, D2, ... Dn;is usually equivalent toT D1; T D2; ... T Dn;where T is a decl-specifier-seq and each Di is an init-declarator. An exception occurs when a name introduced by one ofthe declarators hides a type name used by the decl-specifiers, so that when the same decl-specifiers are used in a subsequentdeclaration, they do not have the same meaning, as instruct S ... ;S S, T; // declare two instances of struct Swhich is not equivalent tostruct S ... ;S S;S T; // errorAnother exception occurs when T is auto (7.1.6.4), for example:auto i = 1, j = 2.0; // error: deduced types for i and j do not matchas opposed toauto i = 1; // OK: i deduced to have type intauto j = 2.0; // OK: j deduced to have type double182© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)parameters-and-qualifiers:( parameter-declaration-clause ) attribute-specifier-seqopt cv-qualifier-seqoptref-qualifieropt exception-specificationopttrailing-return-type:-> trailing-type-specifier-seq abstract-declaratoroptptr-operator:* attribute-specifier-seqopt cv-qualifier-seqopt& attribute-specifier-seqopt&& attribute-specifier-seqoptnested-name-specifier * attribute-specifier-seqopt cv-qualifier-seqoptcv-qualifier-seq:cv-qualifier cv-qualifier-seqoptcv-qualifier:constvolatileref-qualifier:&&&declarator-id:...opt id-expressionnested-name-specifieropt class-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).5The optional attribute-specifier-seq in a trailing-return-type appertains to the indicated return type.
Thetype-id in a trailing-return-type includes the longest possible sequence of abstract-declarators. [ Note: Thisresolves the ambiguous binding of array and function declarators. [ Example:auto f()->int(*)[4];// function returning a pointer to array[4] of int// not function returning array[4] of pointer to int— end example ] — end note ]8.11Type names[dcl.name]To specify type conversions explicitly, and as an argument of sizeof, alignof, new, or typeid, the name ofa type shall be specified.
This can be done with a type-id, which is syntactically a declaration for a variableor function of that type that omits the name of the entity.type-id:type-specifier-seq abstract-declaratoroptabstract-declarator:ptr-abstract-declaratornoptr-abstract-declaratoropt parameters-and-qualifiers trailing-return-typeabstract-pack-declaratorptr-abstract-declarator:noptr-abstract-declaratorptr-operator ptr-abstract-declaratoroptnoptr-abstract-declarator:noptr-abstract-declaratoropt parameters-and-qualifiersnoptr-abstract-declaratoropt [ constant-expressionopt ] attribute-specifier-seqopt( ptr-abstract-declarator )§ 8.1© ISO/IEC 2011 – All rights reserved183ISO/IEC 14882:2011(E)abstract-pack-declarator:noptr-abstract-pack-declaratorptr-operator abstract-pack-declaratornoptr-abstract-pack-declarator:noptr-abstract-pack-declarator parameters-and-qualifiersnoptr-abstract-pack-declarator [ constant-expressionopt ] attribute-specifier-seqopt...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)////////////intintintintintinti*pi*p[3](*p3i)[3]*f()(*pf)(double)name respectively the types “int,” “pointer to int,” “array of 3 pointers to int,” “pointer to array of 3 int,”“function of (no parameters) returning pointer to int,” and “pointer to a function of (double) returningint.” — end example ]2A type can also be named (often more easily) by using a typedef (7.1.3).8.21Ambiguity resolution[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 constructthat could possibly be a declaration a declaration. [ Note: A declaration can be explicitly disambiguated bya nonfunction-style cast, by an = to indicate initialization or by removing the redundant parentheses aroundthe parameter name. — end note ] [ Example:struct S {S(int);};void foo(double a) {S w(int(a));// function declarationS x(int());// function declarationS y((int)a);// object declarationS z = int(a);// 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;§ 8.2184© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)void *operator new(std::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 thatis the operand of a sizeof or typeid operator, when a type-name is nested in parentheses.
In this case,the choice is between the declaration of a parameter of type pointer to function and the declaration of aparameter with redundant parentheses around the declarator-id. The resolution is to consider the type-nameas a simple-type-specifier rather than a declarator-id. [ Example:class C { };void f(int(C)) { }// 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]);§ 8.2© ISO/IEC 2011 – All rights reserved185ISO/IEC 14882:2011(E)— end example ]8.3Meaning of declarators[dcl.meaning]1A 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. An unqualified-id occurring in a declaratorid shall be a simple identifier except for the declaration of some special functions (12.3, 12.4, 13.5) and forthe declaration of template specializations or partial specializations (14.7).
A declarator-id shall not bequalified except for the definition of a member function (9.3) or static data member (9.4) outside of itsclass, the definition or explicit instantiation of a function or variable member of a namespace outside of itsnamespace, or the definition of an explicit specialization outside of its namespace, or the declaration of afriend function that is a member of another class or namespace (11.3). When the declarator-id is qualified,the declaration shall refer to a previously declared member of the class or namespace to which the qualifierrefers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1))or to a specialization thereof; the member shall not merely have been introduced by a using-declarationin the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id. Thenested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier.
[ Note: If thequalifier is the global :: scope resolution operator, the declarator-id refers to a name declared in the globalnamespace scope. — end note ] The optional attribute-specifier-seq following a declarator-id appertains tothe entity that is declared.2A static, thread_local, extern, register, mutable, friend, inline, virtual, or typedef specifier applies directly to each declarator-id in an init-declarator-list; the type specified for each declarator-id dependson both the decl-specifier-seq and its declarator.3Thus, a declaration of a particular identifier has the formT Dwhere T is of the form attribute-specifier-seqopt decl-specifier-seq and D is a declarator. Following is arecursive procedure for determining the type 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 declarationint unsigned i;the type specifiers int unsigned determine the type “unsigned int” (7.1.6.2). — end example ]5In a declaration attribute-specifier-seqopt 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.11Pointers[dcl.ptr]In a declaration T D where D has the form§ 8.3.1186© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)* attribute-specifier-seqopt cv-qualifier-seqopt D1and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T,” then the type ofthe identifier 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.