Prec.     Page 63     Suiv.

5 Expressions

[expr

  1. [Note: Clause 5 defines the syntax, order of evaluation, and meaning of expressions. An expression is a sequence of operators and operands that specifies a computation. An expression can result in a value and can cause side effects.

  2. Operators can be overloaded, that is, given meaning when applied to expressions of class type (clause 9) or enumeration type (7.2). Uses of overloaded operators are transformed into function calls as described in 13.5. Overloaded operators obey the rules for syntax specified in clause 5, but the requirements of operand  type, lvalue, and evaluation order are replaced by the rules for function call. Relations between operators,  such as ++a meaning a+=1, are not guaranteed for overloaded operators (13.5), and are not guaranteed for operands of type bool.
    --end note]
  3. Clause 5 defines the effects of operators when applied to types for which they have not been overloaded.  Operator overloading shall not modify the rules for the built­in operators, that is, for operators applied to types for which they are defined by this Standard. However, these built­in operators participate in overload  resolution, and as part of that process user­defined conversions will be considered where necessary to convert  the operands to types appropriate for the built­in operator. If a built­in operator is selected, such con­versions  will be applied to the operands before the operation is considered further according to the rules in  clause 5; see 13.3.1.2, 13.6.

  4. Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual  expressions, and the order in which side effects take place, is unspecified 53). Between the previous  and next sequence point a scalar object shall have its stored value modified at most once by the evaluation  of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full  expression; otherwise the behavior is undefined. [Example:

        i = v[ i++];     // the behavior is unspecified
        i = 7, i++, i++; // i becomes 9

        i = ++ i + 1;    // the behavior is unspecified
        i = i + 1;       // the value of i is incremented

    --end example]

  5. If during the evaluation of an expression, the result is not mathematically defined or not in the range of rep­resentable values for its type, the behavior is undefined, unless such an expression is a constant expression  (5.19), in which case the program is ill­formed. [Note: most existing implementations of C++ ignore integer  overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating  point exceptions vary among machines, and is usually adjustable by a library function. ]

  6. If an expression initially has the type "reference to T" (8.3.2, 8.5.3), the type is adjusted to "T" prior to any further analysis, the expression designates the object or function denoted by the reference, and the expres­sion is an lvalue.

  7. An expression designating an object is called an object­expression.

  8. Whenever an lvalue expression appears as an operand of an operator that expects an rvalue for that operand, the lvalue­to­rvalue (4.1), array­to­pointer (4.2), or function­to­pointer (4.3) standard conversions are applied to convert the expression to an rvalue. [Note: because cv­qualifiers are removed from the type of an expression of non­class type when the expression is converted to an rvalue, an lvalue expression of type const int can, for example, be used where an rvalue expression of type int is required. ]
     

    Prec.     Page 64     Suiv.

  9. Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
    [Note: otherwise, the only remaining case is that both operands are int ]
  10. The values of the floating operands and the results of floating expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby 55).

5.1 Primary expressions

[expr.prim]

  1. Primary expressions are literals, names, and names qualified by the scope resolution operator ::.

        primary­expression:
            literal
            this
            ( expression )
            id­expression

        id­expression:
            unqualified­id
            qualified­id

        unqualified­id:
            identifier
            operator­function­id
            conversion­function­id
            ~ class­name
        template­id

  2. A literal is a primary expression. Its type depends on its form (2.13). A string literal is an lvalue; all other literals are rvalues.
  3. The keyword this names a pointer to the object for which a nonstatic member function (9.3.2) is invoked. The keyword this shall be used only inside a nonstatic class member function body (9.3) or in a constructor mem­initializer (12.6.2). The type of the expression is a pointer to the function's class (9.3.2), possibly
    with cv­qualifiers on the class type. The expression is an rvalue.
  4. The operator :: followed by an identifier, a qualified­id, or an operator­function­id is a primary­expression. Its type is specified by the declaration of the identifier, qualified­id, or operator­function­id. The result is the entity denoted by the identifier, qualified­id, or operator­function­id. The result is an lvalue if the entity is a function or variable. The identifier, qualified­id, or operator­function­id shall have global namespace scope or be visible in global scope because of a using­directive (7.3.4).
     

    Prec.      Page 65     Suiv.

    [Note: the use of :: allows a type, an object, a function, an enumerator, or a namespace declared in the global namespace to be referred to even if its identifier has been hidden (3.4.3). ]

  5. A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression. The presence of parentheses does not affect whether the expression is an lvalue. The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated.
  6. An id­expression is a restricted form of a primary­expression. [Note: an id­expression can appear after . and ­> operators (5.2.5). ]
  7. An identifier is an id­expression provided it has been suitably declared (clause 7). [Note: for operator­function­ids, see 13.5; for conversion­function­ids, see 12.3.2; for template­ids, see 14.2. A class­name prefixed by ~ denotes a destructor; see 12.4. Within the definition of a nonstatic member function, an identifier that names a nonstatic member is transformed to a class member access expression (9.3.1)]. The type of the expression is the type of the identifier. The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member.
     

        qualified­id:
            :: opt nested­name­specifier templateopt unqualified­id
            :: identifier
            :: operator­function­id
            :: template­id

        nested­name­specifier:
            class­or­namespace­name :: nested­name­specifieropt
            class­or­namespace­name :: template nested­name­specifier

        class­or­namespace­name:
            class­name
            namespace­name

    A nested­name­specifier that names a class, optionally followed by the keyword template (14.8.1), and then followed by the name of a member of either that class (9.2) or one of its base classes (clause 10), is a qualified­id; 3.4.3.1 describes name lookup for class members that appear in qualified­ids. The result is the member. The type of the result is the type of the member. The result is an lvalue if the member is a static member function or a data member. [Note: a class member can be referred to using a qualified­id at any point in its potential scope (3.3.6). ] Where class­name :: class­ name is used, and the two class­names refer to the same class, this notation names the constructor (12.1). Where class­ name :: ~ class­name is used, the two class­names shall refer to the same class; this notation names the destructor (12.4). [Note: a typedef­name that names a class is a class­name (7.1.3). Except as the identifier in the declarator for a con­structor or destructor definition outside of a class member­specification (12.1, 12.4), a typedef­name that names a class may be used in a qualified­id to refer to a constructor or destructor. ]

  8. A nested­name­specifier that names a namespace (7.3), followed by the name of a member of that namespace (or the name of a member of a namespace made visible by a using­directive ) is a qualified­id; 3.4.3.2 describes name lookup for namespace members that appear in qualified­ids. The result is the member. The type of the result is the type of the member. The result is an lvalue if the member is a function or a variable.
  9. In a qualified­id, if the id­expression is a conversion­function­id, its conversion­type­ id shall denote the same type in both the context in which the entire qualified­id occurs and in the context of the class denoted by the nested­name­specifier.
  10. An id­expression that denotes a nonstatic data member or nonstatic member function of a class can only be used:
  11. A template­id shall be used as an unqualified­ide only as specified in 14.7.2, 14.7, and 14.5.4.

  12.  

    Prec.     Page 66     Suiv.

5.2 Postfix expressions

[expr.post

  1. Postfix expressions group left­to­right.

  2.  

     
     
     

        postfix­expression:
            primary­expression
            postfix­expression [ expression ]
            postfix­expression ( expression­ listopt)
            simple­type­ specifier ( expression­listop )
            typename :: opt nested­name­specifier identifier ( expression­ listop )
            typename :: opt nested­name­specifier templateopt template­ id ( expression­listop )
            postfix­expression . templateopt id­expression
            postfix­expression ­> templateopt id­expression
            postfix­expression . pseudo­destructor­name
            postfix­expression ­> pseudo­destructor­name
            postfix­expression ++
            postfix­expression ­­
            dynamic_cast < type­id > ( expression )
            static_cast < type­id > ( expression )
            reinterpret_cast < type­id > ( expression )
            const_cast < type­id > ( expression )
            typeid ( expression )
            typeid ( type id )

        expression­list:
            assignment­expression
            expression­list , assignment­expression

        pseudo­destructor­name:
            :: opt nested­name­specifieropt type­name :: ~ type­name
            :: opt nested­name­specifier template template­ id :: ~ type­name
            :: opt nested­name­specifieropt~ type­name

5.2.1 Subscripting

[expr.sub

  1. A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type "pointer to T" and the other shall have enumeration or integral type. The result is an lvalue of type "T." The type "T" shall be a completely­defined object type. 56) The expression E1[ E2] is identical (by definition) to *(( E1)+( E2)). [Note: see 5.3 and 5.7 for details of * and + and 8.3.4 for details of arrays. ]

5.2.2 Function call

[expr.call

  1. There are two kinds of function call: ordinary function call and member function 57) (9.3) call. A function call is a postfix expression followed by parentheses containing a possibly empty, comma­separated list of expressions which constitute the arguments to the function. For an ordinary function call, the postfix expression shall be either an lvalue that refers to a function (in which case the function­to­pointer standard conversion (4.3) is suppressed on the postfix expression), or it shall have pointer to function type. Calling a function through an expression whose function type has a language linkage that is different from the

  2. Prec.     Page 67     Suiv.


    language linkage of the function type of the called function's definition is undefined (7.5). For a member function call, the postfix expression shall be an implicit (9.3.1, 9.4) or explicit class member access (5.2.5) whose id­expression is a function member name, or a pointer-to­member expression (5.5) selecting a function member. The first expression in the postfix expression is then called the object expression, and the call is as a member of the object pointed to or referred to. In the case of an implicit class member access, the implied object is the one pointed to by this. [Note: a member function call of the form f() is interpreted as (* this). f() (see 9.3.1). ] If a function or member function name is used, the name can be over­loaded (clause 13), in which case the appropriate function shall be selected according to the rules in 13.3. The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function is virtual and is not specified using a qualified­id then the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression. 12.7 describes the behavior of virtual function calls when the object­expression refers to an object under construction or destruction. ]

  3. If no declaration of the called function is visible from the scope of the call the program is ill­formed.
  4. The type of the function call expression is the return type of the statically chosen function (i. e., ignoring the virtual keyword), even if the type of the function actually called is different. This type shall be a com­plete object type, a reference type or the type void.
  5. When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. When a function is called, the parameters that have object type shall have completely­defined object type. [Note: this still allows a parameter to be a pointer or reference to an incomplete class type. However, it prevents a passed­ by­value parameter to have an incomplete class type. ] During the initial­ization of a parameter, an implementation may avoid the construction of extra temporaries by combining the conversions on the associated argument and/ or the construction of temporaries with the initialization of the parameter (see 12.2). The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function. [Example: the access of the constructor, conversion functions or destructor is checked at the point of call in the calling function. If a constructor or destructor for a function parameter throws an exception, the search for a handler starts in the scope of the calling function; in particular, if the function called has a function­try­block (clause 15) with a handler that could handle the exception, this handler is not considered. ] The value of a function call is the value returned by the called function except in a virtual function call if the return type of the final overrider is different from the return type of the statically chosen function, the value returned from the final overrider is converted to the return type of the statically chosen function.
  6. [Note: a function can change the values of its non­const parameters, but these changes cannot affect the val­ues of the arguments except where a parameter is of a reference type (8.3.2); if the reference is to a const­qualified type, const_cast is required to be used to cast away the constness in order to modify the argument's value. Where a parameter is of const reference type a temporary object is introduced if needed (7.1.5, 2.13, 2.13.4, 8.3.4, 12.2). In addition, it is possible to modify the values of nonconstant objects through pointer parameters. ]
  7. A function can be declared to accept fewer arguments (by declaring default arguments (8.3.6)) or more arguments (by using the ellipsis, ... 8.3.5) than the number of parameters in the function definition (8.4). [Note: this implies that, except where the ellipsis (...) is used, a parameter is available for each argument. ]
  8. When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.7). The lvalue­to­rvalue (4.1), array­to­pointer (4.2), and function­to­pointer (4.3) standard conversions are performed on the argument expression. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill­formed. If the argument has a non­POD class type (clause 9), the behavior is undefined. If the argument has integral or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call. These promotions are referred to as the default argument promotions.

  9. Prec.     Page 68     Suiv.

     
  10. The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect before the function is entered. The order of evaluation of the postfix expression and the argu­ment expression list is unspecified.
  11. Recursive calls are permitted, except to the function named main (3.6.1).
  12. A function call is an lvalue if and only if the result type is a reference.

5.2.3 Explicit type conversion (functional notation)

[expr.type.conv] 

  1. A simple­type­specifier (7.1.5) followed by a parenthesized expression­ list constructs a value of the specified type given the expression list. If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4). If the simple­type­specifier specifies a class type, the class type shall be complete. If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5, 12.1), and the expression T( x1, x2, ...) is equivalent in effect to the declaration T t( x1, x2, ...); for some invented temporary variable t, with the result being the value of t as an rvalue.
  2. The expression T(), where T is a simple­type­specifier (7.1.5.2) for a non­array complete object type or the (possibly cv­qualified) void type, creates an rvalue of the specified type, whose value is determined by default­initialization (8.5; no initialization is done for the void() case). [Note: if T is a non­class type that is cv­qualified, the cv­qualifiers are ignored when determining the type of the resulting rvalue (3.10).]

5.2.4 Pseudo destructor call

[expr.type.pseudo];

  1. The use of a pseudo­destructor­name after a dot . or arrow ­> operator represents the destructor for the non­ class type named by type­name. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix­expression before the dot or arrow.
  2. The left hand side of the dot operator shall be of scalar type. The left hand side of the arrow operator shall be of pointer to scalar type. This scalar type is the object type. The type designated by the pseudo­destructor­ name shall be the same as the object type. Furthermore, the two type­ names in a pseudo­destructor­name of the form

  3.  

     
     
     

        :: opt nested­name­specifier opt type­name :: ~ type­name

    shall designate the same scalar type. The cv­unqualified versions of the object type and of the type desig­nated by the pseudo­ destructor­name shall be the same type.

5.2.5 Class member access

[expr.ref]

  1. A postfix expression followed by a dot . or an arrow ­>, optionally followed by the keyword template (14.8.1), and then followed by an id­expression, is a postfix expression. The postfix expression before the dot or arrow is evaluated; 58) the result of that evaluation, together with the id­expression, determine the result of the entire postfix expression.
  2. For the first option (dot) the type of the first expression (the object expression) shall be "class object" (of a complete type). For the second option (arrow) the type of the first expression (the pointer expression) shall be "pointer to class object" (of a complete type). In these cases, the id­expression shall name a member of the class or of one of its base classes. [Note: because the name of a class is inserted in its class scope (clause 9), the name of a class is also considered a nested member of that class. ] [Note: 3.4.5 describes how names are looked up after the . and ­> operators. ]

  3.   


    Prec.     Page 69     Suiv.
  4. If E1 has the type "pointer to class X," then the expression E1­> E2 is converted to the equivalent form (*( E1)). E2; the remainder of 5.2.5 will address only the first option (dot) 59) . Abbreviating object­expression. id­expression as E1. E2, then the type and lvalue properties of this expression are determined as follows. In the remainder of 5.2.5, cq represents either const or the absence of const; vq represents either volatile or the absence of volatile. cv represents an arbitrary set of cv­qualifiers, as defined in 3.9.3.
  5. If E2 is declared to have type "reference to T", then E1. E2 is an lvalue; the type of E1. E2 is T. Other­wise, one of the following rules applies.
  6. [Note: "class objects" can be structures (9.2) and unions (9.5). Classes are discussed in clause 9. ]

5.2.6 Increment and decrement

[expr.post.incr] 

  1. The value obtained by applying a postfix ++ is the value that the operand had before applying the operator. [Note: the value obtained is a copy of the original value ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a complete object type. After the result is noted, the value of the object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true. [Note: this use is deprecated, see annex D. ] The result is an rvalue. The type of the result is the cv­unqualified version of the type of the operand. See also 5.7 and 5.17.
  2. The operand of postfix ­­ is decremented analogously to the postfix ++ operator, except that the operand shall not be of type bool. [Note: For prefix increment and decrement, see 5.3.2. ]

Prec.     Page 70     Suiv.

5.2.7 Dynamic cast

[expr.dynamic.cast] 

  1. The result of the expression dynamic_cast< T>( v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or "pointer to cv void". Types shall not be defined in a dynamic_cast. The dynamic_cast operator shall not cast away constness (5.2.11).
  2. If T is a pointer type, v shall be an rvalue of a pointer to complete class type, and the result is an rvalue of type T. If T is a reference type, v shall be an lvalue of a complete class type, and the result is an lvalue of the type referred to by T.
  3. If the type of v is the same as the required result type (which, for convenience, will be called R in this description), or it is the same as R except that the class object type in R is more cv­qualified than the class object type in v, the result is v (converted if necessary).
  4. If the value of v is a null pointer value in the pointer case, the result is the null pointer value of type R.
  5. If T is "pointer to cv1 B" and v has type "pointer to cv2 D" such that B is a base class of D, the result is a pointer to the unique B sub­ object of the D object pointed to by v. Similarly, if T is "reference to cv1 B" and v has type "cv2 D" such that B is a base class of D, the result is an lvalue for the unique 60) B sub­object of the D object referred to by v. In both the pointer and reference cases, cv1 shall be the same cv­qualification as, or greater cv­qualification than, cv2, and B shall be an accessible unambiguous base class of D. [Example:

  6.  

     
     
     

        struct B {};
        struct D : B {};
        void foo( D* dp)
        {
            B* bp = dynamic_cast< B*>( dp); // equivalent to B* bp = dp;
        }

    --end example]

  7. Otherwise, v shall be a pointer to or an lvalue of a polymorphic type (10.3).
  8. If T is "pointer to cv void," then the result is a pointer to the most derived object pointed to by v. Otherwise, a run­time check is applied to see if the object pointed or referred to by v can be converted to the type pointed or referred to by T.
  9. The run­time check logically executes as follows:
  10. The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws bad_cast (18.5.2).

  11.  

    Prec.     Page 71     Suiv
    [Example:
        class A { virtual void f(); };
        class B { virtual void g(); };
        class D : public virtual A, private B {};
        void g()
        {
            D d;
            B* bp = (B*)& d;                  // cast needed to break protection
            A* ap = &d;                       // public derivation, no cast needed
            D& dr = dynamic_ cast< D&>(* bp); // fails
            ap = dynamic_cast< A*>( bp);     // fails
            bp = dynamic_cast< B*>( ap);     // fails
            ap = dynamic_cast< A*>(& d);     // succeeds
            bp = dynamic_cast< B*>(& d);     // fails
        }

        class E : public D, public B {};
        class F : public E, public D {};
        void h()
        {
            F f;
            A* ap = &f;                        // succeeds: finds unique A
            D* dp = dynamic_cast< D*>( ap);   // fails: yields 0
                                               // f has two D sub­objects
            E* ep = (E*) ap;                   // ill­formed:
                                               // cast from virtual base
            E* ep1 = dynamic_cast< E*>( ap);  // succeeds
        }

    --end example] [Note: 12.7 describes the behavior of a dynamic_cast applied to an object under construction or destruction. ]

5.2.8 Type identification

[expr.typeid] 

  1. The result of a typeid expression is an lvalue of static type const std:: type_info (18.5.1) and dynamic type const std:: type_info or const name where name is an implementation­defined class derived from std:: type_info which preserves the behavior described in 18.5.1. 61) The lifetime of the object referred to by the lvalue extends to the end of the program. Whether or not the destructor is called for the type_info object at the end of the program is unspecified.
  2. When typeid is applied to an lvalue expression whose type is a polymorphic class type (10.3), the result refers to a type_info object representing the type of the most derived object (1.8) (that is, the dynamic type) to which the lvalue refers. If the lvalue expression is obtained by applying the unary * operator to a pointer 62) and the pointer is a null pointer value (4.10), the typeid expression throws the bad_typeid exception (18.5.3).
  3. When typeid is applied to an expression other than an lvalue of a polymorphic class type, the result refers to a type_info object representing the static type of the expression. Lvalue­to­rvalue (4.1), array­to­pointer (4.2), and function­to­pointer (4.3) conversions are not applied to the expression. If the type of the expression is a class type, the class shall be completely­defined. The expression is not evaluated.
  4. When typeid is applied to a type­id, the result refers to a type_info object representing the type of the type­id. If the type of the type­id is a reference type, the result of the typeid expression refers to a type_info object representing the referenced type. If the type of the type­id is a class type or a reference to a class type, the class shall be completely­ defined. Types shall not be defined in the type­id.

  5. Prec.     Page 72     Suiv.

     
  6. The top­level cv­qualifiers of the lvalue expression or the type­id that is the operand of typeid are always ignored. [Example:

  7.  

     
     
     

        class D { ... };
        D d1;
        const D d2;

        typeid( d1) == typeid( d2); // yields true
        typeid( D) == typeid( const D); // yields true
        typeid( D) == typeid( d2); // yields true
        typeid( D) == typeid( const D&); // yields true

    --end example]

  8. If the header <typeinfo> (18.5.1) is not included prior to a use of typeid, the program is ill­formed.
  9. [Note: 12.7 describes the behavior of typeid applied to an object under construction or destruction. ]

5.2.9 Static cast

[expr.static.cast] 

  1. The result of the expression static_cast< T>( v) is the result of converting the expression v to type T. If T is a reference type, the result is an lvalue; otherwise, the result is an rvalue. Types shall not be defined in a static_cast. The static_cast operator shall not cast away constness (5.2.11).
  2. An expression e can be explicitly converted to a type T using a static_cast of the form static_cast< T>( e) if the declaration "T t( e);" is well­formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is a reference type (8.3.2), and an rvalue otherwise. The expression e is used as an lvalue if and only if the initialization uses it as an lvalue.
  3. Otherwise, the static_cast shall perform one of the conversions listed below. No other conversion shall be performed explicitly using a static_cast.
  4. Any expression can be explicitly converted to type "cv void." The expression value is discarded. [Note: however, if the value is in a temporary variable (12.2), the destructor for that variable is not executed until the usual time, and the value of the variable is preserved for the purpose of executing the destructor. ] The lvalue­to­rvalue (4.1), array­to­pointer (4.2), and function­to­pointer (4.3) standard conversions are not applied to the expression.
  5. An lvalue of type "cv1 B", where B is a class type, can be cast to type "reference to cv2 D", where D is a class derived (clause 10) from B, if a valid standard conversion from "pointer to D" to "pointer to B" exists (4.10), cv2 is the same cv­qualification as, or greater cv­qualification than, cv1, and B is not a virtual base class of D. The result is an lvalue of type "cv2 D." If the lvalue of type "cv1 B" is actually a sub­object of an object of type D, the lvalue refers to the enclosing object of type D. Otherwise, the result of the cast is undefined. [Example:

  6.  

     
     
     

        struct B {};
        struct D : public B {};
        D d;
        B &br = d;

        static_cast< D&>( br); // produces lvalue to the original d object

    --end example]

  7. The inverse of any standard conversion sequence (clause 4), other than the lvalue­to­rvalue (4.1), array­to­pointer (4.2), function­to­pointer (4.3), and boolean (4.12) conversions, can be performed explicitly using static_cast subject to the restriction that the explicit conversion does not cast away constness (5.2.11), and the following additional rules for specific cases:

  8. Prec.     Page 73     Suiv.

     
  9. A value of integral type can be explicitly converted to an enumeration type. The value is unchanged if the integral value is within the range of the enumeration values (7.2). Otherwise, the resulting enumeration value is unspecified.
  10. An rvalue of type "pointer to cv1 B", where B is a class type, can be converted to an rvalue of type "pointer to cv2 D", where D is a class derived (clause 10) from B, if a valid standard conversion from "pointer to D" to "pointer to B" exists (4.10), cv2 is the same cv­qualification as, or greater cv­qualification than, cv1, and B is not a virtual base class of D. The null pointer value (4.10) is converted to the null pointer value of the destination type. If the rvalue of type "pointer to cv1 B"points to a B that is actually a sub­object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
  11. An rvalue of type "pointer to member of D of type cv1 T" can be converted to an rvalue of type "pointer to member of B of type cv2 T", where B is a base class (clause 10) of D, if a valid standard conversion from "pointer to member of B of type T" to "pointer to member of D of type T" exists (4.11), and cv2 is the same cv­qualification as, or greater cv­qualification than, cv1. 63) The null member pointer value (4.11) is con­verted to the null member pointer value of the destination type. If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the result of the cast is undefined. [Note: although class B need not contain the original member, the dynamic type of the object on which the pointer to member is derefer­enced must contain the original member; see 5.5. ]
  12. An rvalue of type "pointer to cv void" can be explicitly converted to a pointer to object type. A value of type pointer to object converted to "pointer to cv void" and back to the original pointer type will have its original value.

5.2.10 Reinterpret cast

[expr.reinterpret.cast]

  1. The result of the expression reinterpret_cast< T>( v) is the result of converting the expression v to type T. If T is a reference type, the result is an lvalue; otherwise, the result is an rvalue and the lvalue­to­rvalue (4.1), array­ to­pointer (4.2), and function­to­pointer (4.3) standard conversions are performed on the the expression v. Types shall not be defined in a reinterpret_cast. Conversions that can be per­formed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_ cast.
  2. The reinterpret_cast operator shall not cast away constness. [Note: see 5.2.11 for the definition of '' casting away constness''. Subject to the restrictions in this section, an expression may be cast to its own type using a reinterpret_cast operator. ]
  3. The mapping performed by reinterpret_cast is implementation­ defined. [Note: it might, or might not, produce a representation different from the original value. ]
  4. A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation­defined [Note: it is intended to be unsurprising to those who know the addressing structure of the underlying machine. ]
  5. A value of integral type or enumeration type can be explicitly converted to a pointer. 64) A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation­defined.
  6. A pointer to a function can be explicitly converted to a pointer to a function of a different type. The effect of calling a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined. Except that converting an rvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are function types) and back to its original type yields the original   value, the result of such a pointer conversion is unspecified. [Note: see also 4.10 for more details of pointer conversions. ]

  7.  

    Prec.     Page 74     Suiv.

     
  8. A pointer to an object can be explicitly converted to a pointer to an object of different type. 65) Except that converting an rvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
  9. The null pointer value (4.10) is converted to the null pointer value of the destination type.
  10. An rvalue of type "pointer to member of X of type T1" can be explicitly converted to an rvalue of type "pointer to member of Y of type T2" if T1 and T2 are both function types or both object types. 66) The null member pointer value (4.11) is converted to the null member pointer value of the destination type. The result of this conversion is unspecified, except in the following cases:
  11. An lvalue expression of type T1 can be cast to the type "reference to T2" if an expression of type "pointer to T1" can be explicitly converted to the type "pointer to T2" using a reinterpret_cast. That is, a reference cast reinterpret_cast< T&>( x) has the same effect as the conversion *reinterpret_cast< T*>(& x) with the built­in & and * operators. The result is an lvalue that refers to the same object as the source lvalue, but with a different type. No temporary is created, no copy is made, and constructors (12.1) or conversion functions (12.3) are not called. 67)

5.2.11 Const cast

[expr.const.cast]

  1. The result of the expression const_cast< T>( v) is of type T. If T is a reference type, the result is an lvalue; otherwise, the result is an rvalue and, the lvalue­to­rvalue (4.1), array­to­pointer (4.2), and function­to­pointer (4.3) standard conversions are performed on the expression v. Types shall not be defined in a const_cast. Conversions that can be performed explicitly using const_cast are listed below. No other conversion shall be performed explicitly using const_cast.
  2. [Note: Subject to the restrictions in this section, an expression may be cast to its own type using a const_cast operator. ]
  3. For two pointer types T1 and T2 where

  4.  

     
     
     

        T1 is cv1,0 pointer to cvl,1 pointer to . . . cv1,n-1 pointer to cv1,n T

    and

        T2 is cv2,0 pointer to cv2,1 pointer to . . . cv2,n-1 pointer to cv2,n T

    where T is any object type or the void type and where cv1,kand cv2,kmay be different cv­qualifications, an rvalue of type T1 may be explicitly converted to the type T2 using a const_cast. The result of a pointer const_cast refers to the original object.

  5. An lvalue of type T1 can be explicitly converted to an lvalue of type T2 using the cast const_cast< T2&> (where T1 and T2 are object types) if a pointer to T1 can be explicitly converted to the type pointer to T2 using a const_ cast. The result of a reference const_cast refers to the origi­nal object.

  6. Prec.     Page 75     Suiv.

     
  7. For a const_cast involving pointers to data members, multi­level pointers to data members and multi­level mixed pointers and pointers to data members (4.4), the rules for const_cast are the same as those used for pointers; the "member" aspect of a pointer to member is ignored when determining where the cv­qualifiers are added or removed by the const_cast. The result of a pointer to data member const_cast refers to the same member as the original (uncast) pointer to data member.
  8. A null pointer value (4.10) is converted to the null pointer value of the destination type. The null member pointer value (4.11) is converted to the null member pointer value of the destination type.
  9. [Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const­qualifier 68) may produce undefined behavior (7.1.5.1). ]
  10. The following rules define the process known as casting away constness. In these rules Tn and Xn represent types. For two pointer types:

  11.  

     
     
     

        X1 is T1cv1,1* . . . cv1,N * where T1 is not a pointer type
        X2 is T2cv2,1 * . . . cv2,M * where T2 is not a pointer type

        K is min( N, M)

    casting from X1 to X2 casts away constness if, for a non­pointer type T there does not exist an implicit con­version (clause 4) from:

        Tcv1,(N-K+1)* cv1,(N-K+2) * . . . cv1, N *
    to
        Tcv2,(M-K+1)* cv2,(M-K+2) * . . . cv2,M *
     

  12. Casting from an lvalue of type T1 to an lvalue of type T2 using a reference cast casts away constness if a cast from an rvalue of type "pointer to T1" to the type "pointer to T2" casts away constness.
  13. Casting from an rvalue of type "pointer to data member of X of type T1" to the type "pointer to data mem­ber of Y of type T2" casts away constness if a cast from an rvalue of type "pointer to T1" to the type"pointer to T2" casts away constness.
  14. For multi­level pointer to members and multi­level mixed pointers and pointer to members (4.4), the"member" aspect of a pointer to member level is ignored when determining if a const cv­ qualifier has been cast away.
  15. [Note: some conversions which involve only changes in cv­ qualification cannot be done using const_cast. For instance, conversions between pointers to functions are not covered because such conversions lead to values whose use causes undefined behavior. For the same reasons, conversions between pointers to member functions, and in particular, the conversion from a pointer to a const member function to a pointer to a non­const member function, are not covered. ]

53) The precedence of operators is not directly specified, but it can be derived from the syntax.

54) As a consequence, operands of type bool, wchar_t, or an enumerated type are converted to some integral type.

55) The cast and assignment operators must still perform their specific conversions as described in 5.4, 5.2.9 and 5.17.

56) This is true even if the subscript operator is used in the following common idiom: &x[0].

57) A static member function (9.4) is an ordinary function.

58) This evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id­expression denotes a static member.

59) Note that if E1 has the type "pointer to class X", then (*(E1))is an lvalue.

60) The most derived object (1.8) pointed or referred to by v can contain other B objects as base classes, but these are ignored.

61) The recommended name for such a class is extended_type_info.

62) If p is an expression of pointer type, then *p, (* p), *( p), ((* p)), *(( p)), and so on all meet this requirement.

63) Function types (including those used in pointer to member function types) are never cv­qualified; see 8.3.5 .

64) Converting an integral constant expression (5.19) with value zero always yields a null pointer (4.10), but converting other expressions that happen to have value zero need not yield a null pointer.

65) The types may have different cv­qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness.

66) T1 and T2may have different cv­qualifiers, subject to the overall restriction that a cannot cast away constness.

67) This is sometimes referred to as a type pun.

68) const_cast is not limited to conversions that cast away a const­qualifier.