27

Given a C++11 enum class, nested inside several long- and ugly-named namespaces:

namespace
    long_and_ugly
{
    enum class
        colour
    {
        red,
        green,
        blue
    };
}

Can aliases be made of the enumeration values? With clang++ 3.5, it is possible to do what follows:

using long_and_ugly::colour; // take all the values into the current namespace
using long_and_ugly::colour::red; // take only 'red' into the current namespace

function_taking_colour_argument( red ); // instead of fully referring to the value

g++ 4.9, however, complains. I can't copy its error message because I can't access the code, but it explicitly complained about the usage of the using directive or declaration. I have also tried this:

using red = long_and_ugly::colour::red;

But it also failed. I'm sorry for not pasting the errors. Nevertheless, I believe you should be able to reproduce it.


Question(s)

  • Is it possible to declare aliases to enumeration values in standard C++11, or was I using a clang extension?

  • If it is, what is the correct syntax?

Community
  • 1
  • 1
djsp
  • 2,174
  • 2
  • 19
  • 40
  • http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1742 – dyp Jun 13 '14 at 19:57
  • `using red = long_and_ugly::colour::red;` That's the syntax for type aliases. I doubt it will be used for anything else soon. – dyp Jun 13 '14 at 19:59
  • @dyp Thank you, the page you linked answered my question. About your last comment, I remember g++ also complained about that form, but I will try it again anyway, as soon as I can. – djsp Jun 13 '14 at 20:01
  • Actually, are you sure clang++ puts all the enumerators "into the current namespace" when writing `using long_and_ugly::colour;`? [The clang++ at coliru disagrees](http://coliru.stacked-crooked.com/a/da4b6c9545ceb212) – dyp Jun 13 '14 at 20:02
  • @dyp I'm amused. It worked, for I was able to use the aliases as template parameters. – djsp Jun 13 '14 at 20:08

2 Answers2

32

Enumerators in using-declarations

The problem is that the standard says that you shall not refer to an enumerator inside an enum class when using specifying a using-declaration.

7.3.3p7 The using declaration [namespace.udecl] (n3337)

A using-declaration shall not name a scoped enumerator.

namespace N {
  enum class E { A };
}

using N::E;    // legal
using N::E::A; // ill-formed, violation of [namespace.udecl]p7

Note: clang does accept both lines above; here's a relevant bug report.

It's perfectly fine to refer to the actual name of the enum class itself, but trying to refer to one of its enumerators is ill-formed.


Enumerators in alias-declarations

The standard says that an alias-declaration can only be used to refer to a type-name, since an enumerator isn't a type, using one in such context is ill-formed.

namespace N {
  enum class E { A };
}

using x = N::E;     // legal, `N::E` is a type
using y = N::E::A;  // ill-formed, `N::E::A` isn't a type

Alternatives to using- and alias-declarations

You could declare a constant having whatever-name-of-your-choice initialized with the value you'd like to "alias":

namespace N {
  enum class E { A };
}

constexpr N::E x = N::E::A;
int main () {
  N::E value = x; // semantically equivalent of `value = N::E::A`
}
Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
4

Sort of:

namespace long_and_ugly {
    enum class colour
    {
        red,
        green,
        blue
    };
}
const colour red = long_and_ugly::colour::red;
MSalters
  • 173,980
  • 10
  • 155
  • 350