Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Enumeration declaration

      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
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
      Declarations
       

      Anenumeration is a distinct type whose value is restricted to a range of values (see below for details), which may include several explicitly named constants ("enumerators").

      The values of the constants are values of an integral type known as theunderlying type of the enumeration. An enumeration has the samesize,value representation, andalignment requirements as its underlying type. Furthermore, each value of an enumeration has the same representation as the corresponding value of the underlying type.

      An enumeration is (re)declared using the following syntax:

      enum-keyattr (optional)enum-head-name (optional)enum-base (optional)
      {enumerator-list (optional)}
      (1)
      enum-keyattr (optional)enum-head-name (optional)enum-base (optional)
      {enumerator-list, }
      (2)
      enum-keyattr (optional)enum-head-nameenum-base (optional); (3)(since C++11)
      1)enum-specifier, which appears indecl-specifier-seq of thedeclaration syntax: defines the enumeration type and its enumerators.
      2) A trailing comma can follow theenumerator-list.
      3) Opaque enum declaration: defines the enumeration type but not its enumerators: after this declaration, the type is a complete type and its size is known.
      enum-key -

      enum

      (until C++11)

      one ofenum,enum class, orenum struct

      (since C++11)
      attr -(since C++11) optional sequence of any number ofattributes
      enum-head-name -

      the name of the enumeration that's being declared, it can be omitted.

      (until C++11)

      the name of the enumeration that's being declared, optionally preceded by anested-name-specifier: sequence of names and scope-resolution operators::, ending with scope-resolution operator. It can only be omitted in unscoped non-opaque enumeration declarations.
      nested-name-specifier may only appear if the enumeration name is present and this declaration is a redeclaration. For opaque enumeration declarations,nested-name-specifier can only appear before the name of the enumeration inexplicit specialization declarations.
      Ifnested-name-specifier is present, theenum-specifier cannot refer to an enumeration merely inherited or introduced by ausing declaration, and theenum-specifier can only appear in a namespace enclosing the previous declaration. In such cases,nested-name-specifier cannot begin with adecltype specifier.

      (since C++11)
      enum-base -(since C++11) colon (:), followed by atype-specifier-seq that names an integral type (if it is cv-qualified, qualifications are ignored) that will serve as the fixed underlying type for this enumeration type
      enumerator-list - comma-separated list of enumerator definitions, each of which is either simply a uniqueidentifier, which becomes the name of the enumerator, or a unique identifier with a constant expression:identifier=constant-expression.In either case, theidentifier can be directly followed by an optionalattribute specifier sequence.(since C++17)

      There are two distinct kinds of enumerations:unscoped enumeration (declared with theenum-keyenum) andscoped enumeration (declared with theenum-keyenum class orenum struct).

      Contents

      [edit]Unscoped enumerations

      enumname (optional){enumerator=constant-expression,enumerator=constant-expression, ...} (1)
      enumname (optional):type{enumerator=constant-expression,enumerator=constant-expression, ...} (2)(since C++11)
      enumname:type; (3)(since C++11)
      1) Declares an unscoped enumeration type whose underlying type is not fixed (in this case, the underlying type is an implementation-defined integral type that can represent all enumerator values; this type is not larger thanint unless the value of an enumerator cannot fit in anint orunsignedint. If theenumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value0. If no integral type can represent all the enumerator values, the enumeration is ill-formed).
      2) Declares an unscoped enumeration type whose underlying type is fixed.
      3) Opaque enum declaration for an unscoped enumeration must specify the name and the underlying type.

      Eachenumerator becomes a named constant of the enumeration's type (that is,name), visible in the enclosing scope, and can be used whenever constants are required.

      enum Color{ red, green, blue};Color r= red; switch(r){case red:std::cout<<"red\n";break;case green:std::cout<<"green\n";break;case blue:std::cout<<"blue\n";break;}

      Each enumerator is associated with a value of the underlying type. When= are provided in anenumerator-list, the values of enumerators are defined by those associatedconstant-expressions. If the first enumerator does not have=, the associated value is zero. For any other enumerator whose definition does not have an=, the associated value is the value of the previous enumerator plus one.

      enum Foo{ a, b, c=10, d, e=1, f, g= f+ c};//a = 0, b = 1, c = 10, d = 11, e = 1, f = 2, g = 12

      Thename of an unscoped enumeration may be omitted: such declaration only introduces the enumerators into the enclosing scope:

      enum{ a, b, c=0, d= a+2};// defines a = 0, b = 1, c = 0, d = 2

      When an unscoped enumeration is a class member, its enumerators may be accessed using class member access operators. and->:

      struct X{enum direction{ left='l', right='r'};};X x;X* p=&x; int a= X::direction::left;// allowed only in C++11 and laterint b= X::left;int c= x.left;int d= p->left;

      In thedeclaration specifiers of amember declaration, the sequence

      enumenum-head-name:

      is always parsed as a part of enumeration declaration:

      struct S{enum E1:int{};enum E1:int{};// error: redeclaration of enumeration,// NOT parsed as a zero-length bit-field of type enum E1}; enum E2{ e1}; void f(){false? newenum E2:int();// OK: 'int' is NOT parsed as the underlying type}
      (since C++11)

      [edit]Enumeration name for linkage purposes

      An unnamed enumeration that does not have atypedef name for linkage purposes and that has an enumerator is denoted, forlinkage purposes, by its underlying type and its first enumerator; such an enumeration is said to have an enumerator as aname for linkage purposes.

      [edit]Scoped enumerations

      enum struct|classname{enumerator=constant-expression,enumerator=constant-expression, ...} (1)
      enum struct|classname:type{enumerator=constant-expression,enumerator=constant-expression, ...} (2)
      enum struct|classname; (3)
      enum struct|classname:type; (4)
      1) declares a scoped enumeration type whose underlying type isint (the keywordsclass andstruct are exactly equivalent)
      2) declares a scoped enumeration type whose underlying type istype
      3) opaque enum declaration for a scoped enumeration whose underlying type isint
      4) opaque enum declaration for a scoped enumeration whose underlying type istype

      Eachenumerator becomes a named constant of the enumeration's type (that is,name), which is contained within the scope of the enumeration, and can be accessed using scope resolution operator. There are no implicit conversions from the values of a scoped enumerator to integral types, althoughstatic_cast may be used to obtain the numeric value of the enumerator.

      Run this code
      #include <iostream> int main(){enumclass Color{ red, green=20, blue};    Color r= Color::blue; switch(r){case Color::red:std::cout<<"red\n";break;case Color::green:std::cout<<"green\n";break;case Color::blue:std::cout<<"blue\n";break;} // int n = r; // error: no implicit conversion from scoped enum to intint n=static_cast<int>(r);// OK, n = 21std::cout<< n<<'\n';// prints 21}
      (since C++11)

      An enumeration can be initialized from an integer without a cast, usinglist initialization, if all of the following are true:

      • The initialization is direct-list-initialization.
      • The initializer list has only a single element.
      • The enumeration is either scoped or unscoped with underlying type fixed.
      • The conversion is non-narrowing.

      This makes it possible to introduce new integer types (e.g.SafeInt) that enjoy the same existing calling conventions as their underlying integer types, even on ABIs that penalize passing/returning structures by value.

      enum byte:unsignedchar{};// byte is a new integer type; see also std::byte (C++17)byte b{42};// OK as of C++17 (direct-list-initialization)byte c={42};// errorbyte d= byte{42};// OK as of C++17; same value as bbyte e{-1};// error struct A{ byte b;};A a1={{42}};// error (copy-list-initialization of a constructor parameter)A a2={byte{42}};// OK as of C++17 void f(byte);f({42});// error (copy-list-initialization of a function parameter) enumclass Handle:std::uint32_t{ Invalid=0};Handle h{42};// OK as of C++17
      (since C++17)


      usingenum declaration

      using enumusing-enum-declarator;(since C++20)
      declarator - a (possibly qualified)identifier orsimple template identifiers


      declarator must name a non-dependent enumeration type. The enumeration declarations are found by type-only ordinaryqualified orunqualified lookup, depending on whetherdeclarator is qualified.

      enum E{ x}; void f(){int E;usingenum E;// OK} using F= E;usingenum F;// OK template<class T>using EE= T; void g(){usingenum EE<E>;// OK}

      Ausingenum declaration introduces the enumerator names of the named enumeration as if by ausing declaration for each enumerator. When in class scope, ausingenum declaration adds the enumerators of the named enumeration as members to the scope, making them accessible for member lookup.

      enumclass fruit{ orange, apple}; struct S{usingenum fruit;// OK: introduces orange and apple into S}; void f(){    S s;    s.orange;// OK: names fruit::orange    S::orange;// OK: names fruit::orange}

      Twousingenum declarations that introduce two enumerators of the same name conflict.

      enumclass fruit{ orange, apple};enumclass color{ red, orange}; void f(){usingenum fruit;// OK// using enum color; // error: color::orange and fruit::orange conflict}
      (since C++20)

      [edit]Notes

      Values of unscoped enumeration type can bepromoted orconverted to integral types:

      enum color{ red, yellow, green=20, blue};color col= red;int n= blue;// n == 21

      Values of integer, floating-point, and enumeration types can be converted to any enumeration type by usingstatic_cast. Note that the value after such conversion may not necessarily equal any of the named enumerators defined for the enumeration:

      enum access_t{ read=1, write=2, exec=4};// enumerators: 1, 2, 4 range: 0..7access_t rwe=static_cast<access_t>(7);assert((rwe& read)&&(rwe& write)&&(rwe& exec)); access_t x=static_cast<access_t>(8.0);// undefined behavior since CWG 1766access_t y=static_cast<access_t>(8);// undefined behavior since CWG 1766 enum foo{ a=0, b=UINT_MAX};// range: [0, UINT_MAX]foo x= foo(-1);// undefined behavior since CWG 1766,// even if foo's underlying type is unsigned int
      Feature-test macroValueStdFeature
      __cpp_enumerator_attributes201411L(C++17)Attributes for enumerators
      __cpp_using_enum201907L(C++20)using enum

      [edit]Keywords

      enum,struct,class,using

      [edit]Example

      Run this code
      #include <cstdint>#include <iostream> // enum that takes 16 bitsenum smallenum:std::int16_t{    a,    b,    c}; // color may be red (value 0), yellow (value 1), green (value 20), or blue (value 21)enum color{    red,    yellow,    green=20,    blue}; // altitude may be altitude::high or altitude::lowenumclass altitude:char{    high='h',    low='l',// trailing comma only allowed after CWG 518};  // the constant d is 0, the constant e is 1, the constant f is 3enum{    d,    e,    f= e+2}; // enumeration types (both scoped and unscoped) can have overloaded operatorsstd::ostream& operator<<(std::ostream& os, color c){switch(c){case red: os<<"red";break;case yellow: os<<"yellow";break;case green: os<<"green";break;case blue: os<<"blue";break;default: os.setstate(std::ios_base::failbit);}return os;} std::ostream& operator<<(std::ostream& os, altitude al){return os<<static_cast<char>(al);} // The scoped enum (C++11) can be partially emulated in earlier C++ revisions: enumstruct E11{ x, y};// since C++11 struct E98{enum{ x, y};};// OK in pre-C++11 namespace N98{enum{ x, y};}// OK in pre-C++11 struct S98{staticconstint x=0, y=1;};// OK in pre-C++11 void emu(){std::cout<<(static_cast<int>(E11::y)+ E98::y+ N98::y+ S98::y)<<'\n';// 4} namespace cxx20{enumclass long_long_long_name{ x, y}; void using_enum_demo(){std::cout<<"C++20 `using enum`: __cpp_using_enum == ";switch(auto rnd=[]{return long_long_long_name::x;}; rnd()){#if defined(__cpp_using_enum)usingenum long_long_long_name;case x:std::cout<< __cpp_using_enum<<"; x\n";break;case y:std::cout<< __cpp_using_enum<<"; y\n";break;#elsecase long_long_long_name::x:std::cout<<"?; x\n";break;case long_long_long_name::y:std::cout<<"?; y\n";break;#endif}}} int main(){    color col= red;    altitude a;    a= altitude::low; std::cout<<"col = "<< col<<'\n'<<"a = "<< a<<'\n'<<"f = "<< f<<'\n';     cxx20::using_enum_demo();}

      Possible output:

      col = reda = lf = 3C++20 `using enum`: __cpp_using_enum == 201907; x

      [edit]Defect reports

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

      DRApplied toBehavior as publishedCorrect behavior
      CWG 377C++98the behavior was unspecified when no integral
      type can represent all the enumerator values
      the enumeration is ill-
      formed in this case
      CWG 518C++98a trailing comma was not allowed after the enumerator listallowed
      CWG 1514C++11a redefinition of enumeration with fixed underlying type
      could be parsed as a bit-field in a class member declaration
      always parsed as a redefinition
      CWG 1638C++11grammar of opaque enumeration declaration
      prohibited use for template specializations
      nested-name-specifier
      permitted
      CWG 1766C++98casting an out-of-range value to an enumeration
      without fixed underlying type had an unspecified result
      the behavior is undefined
      CWG 1966C++11the resolution ofCWG issue 1514 made the:
      of a conditional expression part ofenum-base
      only apply the resolution to
      member declaration specifiers
      CWG 2156C++11enum definitions could define
      enumeration types by using-declarations
      prohibited
      CWG 2157C++11the resolution ofCWG issue 1966 did
      not cover qualified enumeration names
      covered
      CWG 2530C++98an enumerator list could contain multiple
      enumerators with the same identifier
      prohibited
      CWG 2590C++98the size, value representation and alignment requirements
      of an enumeration did not depend on its underlying type
      all of them are identical to
      those of the underlying type
      CWG 2621C++20the enumeration name lookup used in
      usingenum declarations was unclear
      made clear
      CWG 2877C++20the enumeration name lookup used in
      usingenum declarations was not type-only
      made type-only

      [edit]References

      • C++23 standard (ISO/IEC 14882:2024):
      • 9.7.1 Enumeration declarations [dcl.enum]
      • C++20 standard (ISO/IEC 14882:2020):
      • 9.7.1 Enumeration declarations [dcl.enum]
      • C++17 standard (ISO/IEC 14882:2017):
      • 10.2 Enumeration declarations [dcl.enum]
      • C++14 standard (ISO/IEC 14882:2014):
      • 7.2 Enumeration declarations [dcl.enum]
      • C++11 standard (ISO/IEC 14882:2011):
      • 7.2 Enumeration declarations [dcl.enum]
      • C++03 standard (ISO/IEC 14882:2003):
      • 7.2 Enumeration declarations [dcl.enum]
      • C++98 standard (ISO/IEC 14882:1998):
      • 7.2 Enumeration declarations [dcl.enum]

      [edit]See also

      (C++11)
      checks if a type is an enumeration type
      (class template)[edit]
      checks if a type is a scoped enumeration type
      (class template)[edit]
      obtains the underlying integer type for a given enumeration type
      (class template)[edit]
      converts an enumeration to its underlying type
      (function template)[edit]
      C documentation forEnumerations
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/enum&oldid=175215"

      [8]ページ先頭

      ©2009-2025 Movatter.jp