Russian Qt Forum
Ноябрь 22, 2024, 05:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Ассоциации (?)  (Прочитано 7547 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Декабрь 05, 2020, 10:52 »

Добрый день

Есть такие данные

Код
C++ (Qt)
enum {
 param_Amount = 0,
 param_Velocity = 1,
 param_..,
 ...
};
 
std::vector<QString> paramNames = {
 "Amount",
 "Velocity",
 ...
};
Как я могу быть уверен что enum соответствует строке имени? При большом числе данных (и/или частых изменениях) это оказывается совсем не простым

Спвсибо
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Декабрь 05, 2020, 14:11 »

в данном случае — никак. а в Qt для этого есть QMetaEnum.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Декабрь 05, 2020, 14:48 »

можно поменять вектор на пару энум-строка и использовать богомерзкие макросы для описания элементов.
приправить static_assert для проверки валидности массива
Записан
RedDog
Частый гость
***
Offline Offline

Сообщений: 221


Просмотр профиля
« Ответ #3 : Декабрь 05, 2020, 17:43 »

Можно мапу/хеш завести
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Декабрь 06, 2020, 12:13 »

в данном случае — никак. а в Qt для этого есть QMetaEnum.
"A можно пример?"  Улыбающийся

можно поменять вектор на пару энум-строка и использовать богомерзкие макросы для описания элементов.
приправить static_assert для проверки валидности массива
Но сначала придется все равно объявить enum чтобы юзать его в паре
Можно мапу/хеш завести
Да, часто достаточно и вектора пар. но тогда потребуется find. С хешем выглядит примерно так
Код
C++ (Qt)
QString Param2Name( TParam param )
{
 static QHash<TParam, QString> names;
 if (!names.size()) {
   names[param_Amount] = "Amount";
   names[param_Velocity] = "Velocity";
   ...
 }
 return names.value(param);
}
Терпимо, но элегантностью не блещет, да и нет гарантии (компилятора) что все enum'ы будут в хеше
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #5 : Декабрь 06, 2020, 15:06 »

Код
C++ (Qt)
class ItemQuality
{
   Q_GADGET
   Q_ENUMS(ItemQualityEnum)
 
public:
   enum ItemQualityEnum
   {
       LowQuality = 1,
       Normal,
       HighQuality,
       Magic,
       Set,
       Rare,
       Unique,
       Crafted,
       Honorific
   };
};
 
const char *quality = metaEnumFromName<Enums::ItemQuality>("ItemQualityEnum").valueToKey(item->quality);

код писался еще под 4.8.7 и до С++11, может щас можно как-то получше.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Декабрь 07, 2020, 12:17 »

Код
C++ (Qt)
const char *quality = metaEnumFromName<Enums::ItemQuality>("ItemQualityEnum").valueToKey(item->quality);
Ну как-то это выглядит монструозно или неадекватно для скромной цели стартового поста Улыбающийся Возможно там задумка печатать такие enum'ы автоматом

код писался еще под 4.8.7 и до С++11, может щас можно как-то получше.
Да, я тоже рассчитывал на какую-нить "фишку" из новых стандартов. Хотя сам дальше С++ 11 пока не уполз  Улыбающийся

В любом случае спасибо за пример
Записан
AkonResumed
Чайник
*
Offline Offline

Сообщений: 81


Просмотр профиля
« Ответ #7 : Апрель 03, 2021, 08:09 »

Хз. Год прошел. Но если прям нужна уверенность, то, навскидку, как-то так:
Код:
#include <iostream>

enum Param {
First,
Second,
Third
};

template <Param> const char* ParamName = "Not associated!";
template <> const char* ParamName<First> = "First parameter name";
template <> const char* ParamName<Second> = "Second parameter name";

// Для третьего параметра "забыли" специализацию, поэтому будет "Not associated!".

int main()
{
std::cout << ParamName<First> << std::endl;
std::cout << ParamName<Second> << std::endl;
std::cout << ParamName<Third> << std::endl;  // Not associated!

return 0;
}

Или еще лучше - с компайл-тайм детектион:
Код:
template <Param> const char* ParamName = "Not associated!";
заменить на
template <Param> const char* ParamName = [](){ static_assert(0, "Not associated!"); return nullptr; }();
В этом случае строка
std::cout << ParamName<Third> << std::endl;  // Not associated!
просто будет давать ошибку компиляции.

Здесь С++17 (template variables/constants, invokable lambda), но в С++11 это тоже принципиально достижимо.

З.Ы. Сам всегда делал (и делаю) перечисление + массив строк (как у вас). Да, при изменении нужна скрупулезность. Зато достоинство - простота и читаемость кода. Да и часто для строк нужно делать перевод на разные языки, а это уже что-то вроде
QCoreApplication::translate("context", QT_TRANSLATE_NOOP("context", "First parameter name")
и только рантайм.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #8 : Апрель 27, 2021, 22:18 »

https://github.com/Neargye/magic_enum
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Апрель 28, 2021, 11:31 »

Да, вроде "в тему", спасибо. Правда сейчас навалилась др работа..
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #10 : Апрель 28, 2021, 15:56 »

Красивое решение)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #11 : Апрель 28, 2021, 17:27 »

Если нужен свой велик для С++98, то можно что-то типа этого использовать

Код
C++ (Qt)
template < typename _Type, int >
struct EnumName { static const char * name () { return "<Unknown>"; } };
 
#define ENUM_NAME( Enum, param_value, param_name ) \
   template <>  struct EnumName< Enum, param_value > { static const char * name () { return param_name; } }; \
 
template < typename _Enum, int _value >
struct EnumNameHelper
{
   static const char * name ( int value )
   {
       if ( _value == value )
           return EnumName< _Enum, _value >::name();
       else if ( _value > value )
           return EnumNameHelper< _Enum, _value - 1 >::name( value );
       else
           return "<Incorrect>";
   }
};
 
template < typename _Enum >
struct EnumNameHelper< _Enum, -1 >
{
   static const char * name ( int ) { return "<Corrupted>"; }
};
 
template < typename _Enum >
const char * enumValueName ( _Enum value )
{
   return EnumNameHelper< _Enum, param_Count >::name( value );
}
 

Код
C++ (Qt)
enum MyEnum
{
 param_Amount,
 param_Velocity,
 param_Color,
 param_Coordinate,
 param_Count
};
 
// или так писать
template <> struct EnumName< MyEnum, param_Amount > { static const char * name () { return "Amount"; } };
// или так
ENUM_NAME( MyEnum, param_Velocity, "Velocity" )
ENUM_NAME( MyEnum, param_Color, "Color" )
ENUM_NAME( MyEnum, param_Coordinate, "Coordinate" )
 
 
#include <iostream>
 
int main ( int narg, char ** vargs )
{
   // В runtime тоже работает
   for ( size_t i = 0; i < param_Count; ++i )
       ::std::cout << enumValueName< MyEnum >( i ) << ::std::endl;
   return 0;
}
 
« Последнее редактирование: Апрель 29, 2021, 07:40 от ssoft » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.347 секунд. Запросов: 23.