Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Explicit type conversion

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Explicit conversions
      dynamic_cast
      reinterpret_cast
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
      Expressions
      General
      Literals
      Operators
      Conversions
       

      Converts between types using a combination of explicit and implicit conversions.

      Contents

      [edit]Syntax

      (type-id)unary-expression (1)
      simple-type-specifier(expression-list (optional))
      simple-type-specifier(initializer-list (optional))
      (2)(until C++11)
      (since C++11)
      simple-type-specifier{initializer-list (optional)} (3)(since C++11)
      simple-type-specifier{designated-initializer-list} (4)(since C++20)
      typenameidentifier(initializer-list (optional)) (5)(since C++11)
      typenameidentifier{initializer-list (optional)} (6)(since C++11)
      typenameidentifier{designated-initializer-list} (7)(since C++20)

      Explicitly converts any number of values to a value of the target type.

      1) Explicit type conversion (cast notation), also calledC-style cast.
      2-7) Explicit type conversion (functional notation), also calledfunction-style cast.
      type-id - atype-id
      unary-expression - an unary expression (whose top-level operator does not have aprecedence higher than that of C-style cast)
      simple-type-specifier - asimple type specifier
      expression-list - a comma-separated list of expressions (except unparenthesizedcomma expressions)
      initializer-list - a comma-separated list ofinitializer clauses
      designated-initializer-list - a comma-separated list ofdesignated initializer clauses
      identifier - a (possibly qualified) identifier (includingtemplate identifiers)

      [edit]Explanation

      1) When the C-style cast is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:
      a)const_cast<type-id >(unary-expression );
      b)static_cast<type-id >(unary-expression ), with extensions: pointer or reference to aderived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class isinaccessible (that is, this cast ignores the private inheritance specifier). Same applies to castingpointer to member to pointer to member of unambiguous non-virtual base;
      c) astatic_cast (with extensions) followed byconst_cast;
      d)reinterpret_cast<type-id >(unary-expression );
      e) areinterpret_cast followed byconst_cast.
      The first choice that satisfies the requirements of the respective cast operator is selected, even if it is ill-formed (see example). If astatic_cast followed by aconst_cast is used and the conversion can be interpreted in more than one way as such, the conversion is ill-formed.
      In addition, C-style casts can cast from, to, and between pointers to incomplete class type. If bothtype-id and the type ofunary-expression are pointers to incomplete class types, it is unspecified whetherstatic_cast orreinterpret_cast gets selected.
      2-7) A function-style cast specifies atype (simple-type-specifier  oridentifier (since C++11)) and aninitializer (the remaining parts), it constructs a value of the target typeT, which is determined from the specified type and initializer(since C++17):

      T is the specified type.

      (until C++17)

      T is determined as follows:

      • If the specified type is a placeholder for a deduced class type,T is the return type of the function selected by overload resolution forclass template deduction.
      • Otherwise, if the specified type contains aplaceholder type,T is the deduced type.
      (since C++23)
      • Otherwise,T is the specified type.
      (since C++17)
      The conversion result is determined as follows:
      • If the function-style cast is of syntax(2), and there is exactly one expression in parentheses, this cast is equivalent to the corresponding C-style cast.
      • Otherwise, ifT is (possibly cv-qualified)void, the result isan rvalue(until C++11)a prvalue(since C++11) of typevoid that performs no initialization.
      • If the initializer is not(), the program is ill-formed.
      (until C++11)
      • If the initializer is not() or{} afterpack expansion (if any), the program is ill-formed.
      (since C++11)
      • Otherwise, ifT is a reference type, the function-style cast has the same effect asdirect-initializing an invented variablet of typeT from the specified initializer, and the result is the initializedt.
      • The result is an lvalue.
      (until C++11)
      • IfT is an lvalue reference type or an rvalue reference to function type, the result is an lvalue.
      • Otherwise, the result is an xvalue.
      (since C++11)
      • Otherwise, the result isan rvalue(until C++11)a prvalue(since C++11) of of typeTdesignating a temporary(until C++17)whose result object is(since C++17)direct-initialized with the specified initializer.

      [edit]Ambiguity Resolution

      [edit]Ambiguous declaration statement

      In the case of an ambiguity between an expression statement with a function-style cast expression as its leftmost subexpression and a declaration statement, the ambiguity is resolved by treating it as a declaration. This disambiguation is purely syntactic: it does not consider the meaning of names occurring in the statement other than whether they are type names:

      struct M{};struct L{ L(M&);}; M n;void f(){    M(m);// declaration, equivalent to M m;    L(n);// ill-formed declaration, equivalent to L n;    L(l)(m);// still a declaration, equivalent to L l((m));}

      However, if the outermost declarator in the ambiguous declaration statement has atrailing return type, the statement will only be treated as a declaration statement if the trailing return type starts withauto:

      struct M; struct S{    S* operator()();int N;int M; void mem(S s){auto(s)()->M;// expression (S::M hides ::M), invalid before C++23}}; void f(S s){{auto(s)()->N;// expression, invalid before C++23auto(s)()->M;// function declaration, equivalent to M s();}{        S(s)()->N;// expression        S(s)()->M;// expression}}
      (since C++11)

      [edit]Ambiguous function parameter

      The ambiguity above can also occur in the context of a declaration. In that context, the choice is between an object declaration with a function-style cast as the initializer and a declaration involving a function declarator with a redundant set of parentheses around a parameter name. The resolution is also to consider any construct, such as the potential parameter declaration, that could possibly be a declaration to be a declaration:

      struct S{    S(int);}; void foo(double a){    S w(int(a));// function declaration: has a parameter `a` of type int    S x(int());// function declaration: has an unnamed parameter of type int(*)()// that is adjusted from int() // Ways to avoid ambiguity:    S y((int(a)));// object declaration: extra pair of parentheses    S y((int)a);// object declaration: C-style cast    S z=int(a);// object declaration: no ambiguity for this syntax}

      However, if the outermost declarator in the ambiguous parameter declaration has atrailing return type, the ambiguity will only be resolved by treating it as a declaration if it starts withauto:

      typedefstruct BB{int C[2];}*B, C; void foo(){    S a(B()->C);// object declaration: B()->C cannot declare a parameter    S b(auto()->C);// function declaration: has an unnamed parameter of type C(*)()// that is adjusted from C()}
      (since C++11)

      [edit]Ambiguous type-id

      An ambiguity can arise from the similarity between a function-style cast and atype-id. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id:

      // `int()` and `int(unsigned(a))` can both be parsed as type-id:// `int()`            represents a function returning int//                    and taking no argument// `int(unsigned(a))` represents a function returning int//                    and taking an argument of type unsignedvoid foo(signedchar a){    sizeof(int());// type-id (ill-formed)    sizeof(int(a));// expression    sizeof(int(unsigned(a)));// type-id (ill-formed) (int())+1;// type-id (ill-formed)(int(a))+1;// expression(int(unsigned(a)))+1;// type-id (ill-formed)}

      However, if the outermostabstract-declarator in the ambiguoustype-id has atrailing return type, the ambiguity will only be resolved by treating it as a type-id if it starts withauto:

      typedefstruct BB{int C[2];}*B, C; void foo(){    sizeof(B()->C[1]);// OK, sizeof(expression)    sizeof(auto()->C[1]);// error: sizeof of a function returning an array}
      (since C++11)

      [edit]Notes

      Feature-test macroValueStdFeature
      __cpp_auto_cast202110L(C++23)auto(x) andauto{x}

      [edit]Example

      Run this code
      #include <cassert>#include <iostream> double f=3.14;unsignedint n1=(unsignedint)f;// C-style castunsignedint n2=unsigned(f);// function-style cast class C1;class C2;C2* foo(C1* p){return(C2*)p;// casts incomplete type to incomplete type} void cpp23_decay_copy_demo(){auto inc_print=[](int& x,constint& y){++x;std::cout<<"x:"<< x<<", y:"<< y<<'\n';}; int p{1};    inc_print(p, p);// prints x:2 y:2, because param y here is an alias of pint q{1};    inc_print(q,auto{q});// prints x:2 y:1, auto{q} (C++23) casts to prvalue,// so the param y is a copy of q (not an alias of q)} // In this example, C-style cast is interpreted as static_cast// even though it would work as reinterpret_caststruct A{};struct I1: A{};struct I2: A{};struct D: I1, I2{}; int main(){    D* d= nullptr;//  A* a = (A*)d;                   // compile-time error    A* a=reinterpret_cast<A*>(d);// this compilesassert(a== nullptr);     cpp23_decay_copy_demo();}

      Output:

      x:2 y:2x:2 y:1

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 1223
      (P2915R0)
      C++11the addition of trailing return type introduced more ambiguitiesresolves them
      CWG 1893C++11function-style cast did not consider pack expansionsconsiders them
      CWG 2351C++11void{} was ill-formedmade well-formed
      CWG 2620C++98the resolution of ambiguous function
      parameters might be misinterpreted
      improved the wording
      CWG 2828C++98a C-style cast was ill-formed if multiple interpretations
      of astatic_cast followed by aconst_cast exist,
      regardless of whether these conversions are actually used
      only considers the
      conversions
      possibly being used
      CWG 2894C++98function-style casts could create reference rvaluescan only create reference lvalues

      [edit]References

      • C++23 standard (ISO/IEC 14882:2024):
      • 7.6.1.4 Explicit type conversion (functional notation) [expr.type.conv]
      • 7.6.3 Explicit type conversion (cast notation) [expr.cast]
      • C++20 standard (ISO/IEC 14882:2020):
      • 7.6.1.4 Explicit type conversion (functional notation) [expr.type.conv]
      • 7.6.3 Explicit type conversion (cast notation) [expr.cast]
      • C++17 standard (ISO/IEC 14882:2017):
      • 8.2.3 Explicit type conversion (functional notation) [expr.type.conv]
      • 8.4 Explicit type conversion (cast notation) [expr.cast]
      • C++14 standard (ISO/IEC 14882:2014):
      • 5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
      • 5.4 Explicit type conversion (cast notation) [expr.cast]
      • C++11 standard (ISO/IEC 14882:2011):
      • 5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
      • 5.4 Explicit type conversion (cast notation) [expr.cast]
      • C++03 standard (ISO/IEC 14882:2003):
      • 5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
      • 5.4 Explicit type conversion (cast notation) [expr.cast]
      • C++98 standard (ISO/IEC 14882:1998):
      • 5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
      • 5.4 Explicit type conversion (cast notation) [expr.cast]

      [edit]See also

      const_cast conversion adds or removes const[edit]
      static_cast conversion performs basic conversions[edit]
      dynamic_cast conversion performs checked polymorphic conversions[edit]
      reinterpret_cast conversion performs general low-level conversions[edit]
      standard conversions implicit conversions from one type to another[edit]
      C documentation forcast operator
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/explicit_cast&oldid=179764"

      [8]ページ先頭

      ©2009-2025 Movatter.jp