Подтвердить что ты не робот

Возможно ли использовать псевдоним enumerator класса enum?

Учитывая класс перечисления С++ 11, вложенный внутри нескольких пространств имен с длинными и уродливыми именами:

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

Могут ли быть сделаны псевдонимы из значений перечисления? С clang++ 3.5 можно сделать следующее:

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, однако, жалуется. Я не могу скопировать его сообщение об ошибке, потому что я не могу получить доступ к этому коду, но он явно жаловался на использование директивы use или декларации. Я также пробовал это:

using red = long_and_ugly::colour::red;

Но он тоже потерпел неудачу. Прошу прощения за то, что вы не вставляете ошибки. Тем не менее, я считаю, что вы должны иметь возможность воспроизвести его.


Вопрос (ы)

  • Можно ли объявить псевдонимы значениям перечисления в стандартном С++ 11, или я использовал расширение clang?

  • Если это так, то какой правильный синтаксис?

4b9b3361

Ответ 1

Перечислители при использовании-деклараций

Проблема заключается в том, что в стандарте указано, что вы не должны ссылаться на перечислитель внутри класса enum при использовании указания использования-объявления.

7.3.3p7 Объявление using [namespace.udecl] (n3337)

Использование-объявления не должно указывать перечислитель с областью.

namespace N {
  enum class E { A };
}

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

Примечание: clang принимает обе строки выше; здесь соответствующий отчет об ошибке.

Совершенно нормально ссылаться на фактическое имя класса enum, но попытка ссылаться на один из его счетчиков плохо сформирована.


Перечислители в объявлениях псевдонимов

В стандарте указано, что объявление alias может использоваться только для обозначения имени типа, поскольку перечислитель не является типом, поскольку один в таком контексте плохо сформирован.

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

Альтернативы использованию и псевдонимов-деклараций

Вы можете объявить константу с инициализацией any-name-of-your-choice со значением, которое вы хотели бы "псевдоним":

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`
}

Ответ 2

Сортировка:

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