Преобразование элемента типа класса перечисления в соответствующую строку

У меня есть класс перечисления, я пытаюсь создать функцию, которая будет возвращать строку соответствующего члена класса перечисления.

Например, если у меня есть следующий класс перечисления:

enum class SignalState   
{
    red,        // 0
    yellow,     // 1
    green,      // 2
    max_num
};

Я хотел бы вернуть строки «красный», «желтый» или «зеленый», в зависимости от члена SignalState, который я передаю в функцию.

В C это довольно просто, но в C++ у меня возникли некоторые трудности с тем, как это сделать. Для этой задачи я использую std::string_view и std::array.

Вот мой код:

#include <iostream>
#include <string>
#include <string_view>
#include <array>


// Scoped enumerators (enum class) unlike unscoped enumerators (enum)
// won't explicitly convert to integers; you have to cast them, as we did on "signal_string" function

enum class SignalState   //scoped enumerators return the Type member
{
    red,        // 0
    yellow,     // 1
    green,      // 2
    max_num
};


//using C arrays:
/*
static const char* signal_string(SignalState signal)     //this takes an enum as paramenter and returns the matching string
{
    static const char *ss[] = {"Red","Yellow","Green"};

    return ss[ static_cast<unsigned>(signal) ];   //converts enum class "Type" into an unsigned integer, with enum classes as opposed to enum you gotta expliclty convert it
}
*/

    
//using C++:
static const std::string_view signal_string(SignalState signal)    
{
    static const std::array <SignalState, SignalState::max_num> ss {"Red","Yellow","Green"};       

    return ss[ static_cast<unsigned>(signal) ];  
}


int main()
{

    SignalState mysig{SignalState::red};

    std::cout << "Color is: " <<  signal_string(mysig);

    return 0;
}

Ошибка:

error: value of type 'SignalState' is not implicitly convertible to 'size_t' (aka 'unsigned long')

ОБНОВЛЯТЬ: Статическое приведение SignalState внутри массива:

static const std::array <SignalState, static_cast<unsigned>(SignalState::max_num)> ss {"Red","Yellow","Green"};  

Я все еще получаю следующую ошибку:

error: implicit instantiation of undefined template 'std::__1::array<SignalState, 3>'
    static const std::array <SignalState, static_cast<unsigned>(SignalState::max_num)> **ss** {"Red","Yellow","Green"};

Любая помощь приветствуется. Я думаю, что должен быть более простой и понятный способ создания этой функции, не может быть, чтобы в C++ это было сложнее сделать, чем в C. Большое спасибо

ss должен быть массивом string (или string_view), а не массивом элементов типа перечисления (SignalState), поэтому std::array<SignalState, ...> неверно.
wohlstad 13.08.2024 10:07

Этот пост может быть интересен: Как преобразовать перечисление в строку в современном C++.

wohlstad 13.08.2024 10:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Одним из обходных путей является использование const std::map, как показано ниже:

static const std::string_view signal_string(SignalState signal)    
{
    static const std::map<SignalState, std::string_view> myMap = {{SignalState::red,"Red"},{SignalState::yellow,"Yellow"},{SignalState::green,"Green"}};
    
    return myMap.at(signal); 
}

Демо

Это кажется излишним. В чем это преимущество перед простым std::array?

wohlstad 13.08.2024 10:25

@wohlstad Я предложил одно возможное решение. Не обязательно публиковать только лучшее из возможных решений. Любое работающее решение жизнеспособно и полезно для будущих читателей. Я не понимаю, почему вы всегда без причины критикуете ответы других людей. Не обязательно, чтобы ответ имел какое-то преимущество перед другими публикуемыми ответами. Для будущих читателей приемлемо любое жизнеспособное/работающее решение. В зависимости от ситуации читатели могут выбирать. Чем больше выбора у людей/читателей, тем больше они узнают.

Alan 13.08.2024 10:30

Я редко критикую другие ответы и только тогда, когда считаю, что у меня есть веские аргументы. Я всегда делаю это вежливо и прошу разъяснений. Альтернативные решения полезны только в том случае, если они дают какое-то преимущество, и именно об этом я вас и спрашивал. Вы могли бы просто ответить по существу (чего вы не сделали). Не обвиняйте других в несправедливости без уважительной причины.

wohlstad 13.08.2024 10:36

@wohlstad Я не думаю, что мне нужно оправдывать публикацию своего ответа, если в нем нет ничего технически неправильного, а также он не повторяет другие ответы.

Alan 13.08.2024 10:57

Вы что-то упускаете. Это не вопрос оправдания. Это была попытка (явно провальная) обсудить преимущества различных решений. Но я вижу, что вас это не интересует, поэтому не буду продолжать.

wohlstad 13.08.2024 11:01

Таким образом, одно из преимуществ (неупорядоченной) карты перед массивом — широкий диапазон с дырками enum class E{ A= 0, B = 500, C = 2048};. но (упорядоченный) массив парных перечислений, stringview также выполнит эту работу (против упорядоченной карты).

Jarod42 13.08.2024 15:59
Ответ принят как подходящий

Вам следует объявить массив std::string_view, а не массив SignalState. Альтернативно, вы можете позволить вывести параметры шаблона:

std::string_view signal_string(SignalState signal)    
{
    using namespace std::string_view_literals;
    static const std::array ss { "Red"sv, "Yellow"sv, "Green"sv };

    return ss[ static_cast<std::size_t>(signal) ];
}

Вам следует создать массив constexpr, а не только const, и он, конечно, требует проверки границ, чтобы гарантировать отсутствие UB.

cptFracassa 13.08.2024 10:41

Другие вопросы по теме