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.
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?
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
Theusing
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.
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
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`
}