Using Enum

Published Proposal,

This version:
Gašper Ažman <gasper.azman@gmail.com>
Jonathan Müller <jonathan.mueller@nathan.net>



1. Revision History

2. Status of this paper

This paper has been approved by EWG in Kona 2019 and sent to Core with the ship vehicle of C++20.

3. Motivation


    — Dan Saks

Consider an enum class:


Currently, a switch using this enum looks as follows:

std::string_view to_string(rgba_color_channel channel) {
  switch (channel) {
    case rgba_color_channel::red:   return "red";
    case rgba_color_channel::green: return "green";
    case rgba_color_channel::blue:  return "blue";
    case rgba_color_channel::alpha: return "alpha";



using enum rgba_color_channel;


Furthermore, the syntax

using rgba_color_channel::red;


The above example would then be written as

std::string_view to_string(rgba_color_channel channel) {
  switch (my_channel) {
    using enum rgba_color_channel;
    case red:   return "red";
    case green: return "green";
    case blue:  return "blue";
    case alpha: return "alpha";

4. Rationale

4.1. Consistency


4.2. Better Identifiers



4.3. Evidence of Need



5. Proposal

5.1. Syntax: using ENUM_ID::IDENTIFIER

We propose to allow the syntax of





5.2. Syntax: using enum IDENTIFIER

We propose the addition of a new using enum statement:

using enum IDENTIFIER;



6. Examples

6.1. Strongly typed enums with global identifiers


namespace my_lib {

enum class errcode {
  SUCCESS = 0,
  ENOMEM = 1,
  EAGAIN = 2,
using enum errcode;


namespace  {

my_lib::errcode get_widget() {
  using namespace my_lib;


6.2. Switching with no syntax overhead



std::string_view to_string(rgba_color_channel channel) {
  switch (my_channel) {
    using enum rgba_color_channel;
    case red:   return "red";
    case green: return "green";
    case blue:  return "blue";
    case alpha: return "alpha";

6.3. Adding ADL-only Functions to Enumerations:


namespace ns {
  struct E_detail {
    enum E {

int main() {
  auto x = ns::e1;
  auto y = ns::e2;


7. Frequently Asked Questions

7.1. Has this been implemented?


7.2. Can I do this with unscoped enums?

Yes. The motivation for that is the pattern

class foo {
   enum bar {


using enum ::foo::bar;



using my_alias = my::name_space::enum_name;




7.5. Why propose using ENUM_ID::IDENTIFIER at all?

... given that the following already works:

  constexpr auto red = rgba_color_channel::red;

and that, given [P0945R0], this will work:

  using red = rgba_color_channel::red;


8. Proposed Wording

8.1. Preface

The idea is that the identifiers appear as if they were declared in the declarative region where the using-enum-directive appears, and not model the using-directive’s "enclosing namespace" wording.


8.2. Changes

In chapter [namespace.udecl]:

  1. In a using-declaration used as a member-declaration, each using-declarator 's shall either name an enumerator or have a nested-name-specifier shall name naming a base class of the class being defined. [Note: this exception allows the introduction of enumerators into class scope. --end note]

  1. A using-declaration that names a class member that is not an enumerator shall be a member-declaration. [Note: the exception for enumerators allows the introduction of class members that are enumerators into non-class scope --end note]

In chapter [dcl.dcl], in [dcl.enum], add section titled "Using Enum Directive", with the stable reference "[enum.udir]".

    attribute-specifier-seqopt using elaborated-type-specifier;
  1. The elaborated-type-specifier shall name an enumeration. [Note: an elaborated type specifier for an enumeration always begins with enum -- end note]

  2. The elaborated-type-specifier shall not name a dependent type.

  3. The optional attribute-specifier-seq appertains to the using-enum-directive.

  4. A using-enum-directive introduces the enumerator names of the named enumeration into the scope in which it appears, as synonyms for the enumerators of the named enumeration. [Note: this means that they may be used, qualified or unqualified, after the using-enum-directive -- end note]

[Note: an using-enum-directive in class scope adds the enumerators of the named enumeration as members to the scope. This means they are accessible for member lookup. Example:

enum class E { e1, e2 };
struct S {
  using enum E; // introduces e1 and e2 into S
void f() {
  S s;
  s.e1; // well-formed, names E::e1.
  S::e2; // well-formed, names E::e2.
-- end note]


2.17. — it is a using-enum-directive

In [gram.dcl], under block-declaration:


In [class.mem], under member-declaration:


Note to editor:

For greater consistency, rename, everywhere:

9. Acknowledgements

The authors would like to thank Marcel Ebmer and Lisa Lippincott for early feedback, and the members of the BSI C++ WG for further feedback, especially Graham Haynes and Barry Revzin. Even further feedback was provided by Tomas Puverle, who encouraged us to extend it to enums, and Dan Saks for the permission to include a quotation from him. A special thanks to Jeff Snyder who presented this to EWG, and to Richard Smith for pointing out direct injection is really the better way to go. Casey Carter pointed out some issues with wording typography, and realized that this paper allows adding adl-only functions to enumerators.

Another big thank-you to the Wizard of Worde, Richard Smith, who helped with the final wording, and found the need to make enum names non-dependent.


Informative References
