powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Обход enum class в C++11
24 сообщений из 24, страница 1 из 1
Обход enum class в C++11
    #38107808
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Раньше обход enum можно было делать так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#include <iostream>
using namespace std;

enum T1 {
    a1, a2, a3, a4,
    a_count
};

int main() {
    for(size_t i = 0; i < a_count; ++i) 
       cout << i << endl;

    return 0;
}



Теперь в C++11 можно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <iostream>
using namespace std;

enum class T1 {
    a1, a2, a3, a4,
    a_count
};

//T1::operator int() { return static_cast<size_t>(*this); }

int main() {
    for(size_t i = 0; i < static_cast<size_t>(T1::a_count); ++i) 
       cout << i << endl;

    return 0;
}


Можно ли как-то делать обход без постоянных static_cast или можно ли как-то перегрузить operator int для enum class T1?

Если раскоментировать перегрузку оператора, то вылетает ошибка:
автор9:14: internal compiler error: in constructor_name_p, at cp/name-lookup.c:1809
Please submit a full bug report,
with preprocessed source if appropriate.
See < http://gcc.gnu.org/bugs.html> for instructions.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38107880
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В принципе можно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
#include <iostream>
using namespace std;

enum class T1 {
    a1, a2, a3, a4,
    a_count
};

bool operator !=(size_t val1, T1 val2) {
    return !(val1 == static_cast<size_t>(val2)); 
}

int main() {
    for(size_t i = 0; i != T1::a_count; ++i) 
       cout << i << endl;

    return 0;
}


Но как перегрузить именно глобальный оператор приведения типа size_t<->T1?
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38107890
Sheraton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все таки хорошая штука C++11, сразу видно облегчает жизнь программиста.

Было так:
Код: plaintext
1.
for(size_t i = 0; i < a_count; ++i) 



Стало так:
Код: plaintext
1.
 for(size_t i = 0; i < static_cast<size_t>(T1::a_count); ++i) 



А можно даже так:
Код: plaintext
1.
2.
3.
4.
5.
bool operator !=(size_t val1, T1 val2) {
    return !(val1 == static_cast<size_t>(val2)); 
}

for(size_t i = 0; i != T1::a_count; ++i) 



Как говорится улучшение языка на лицо
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38107902
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Sheraton , естественно я привел проблемные/не понятные мне места C++11.
Если бы я привел все косяки старого способа... но это уже другая тема.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108032
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На самом деле скорее всего оба варианта кода, старый и новый, невалидны, потому что значения enum должны быть по стандарту уникальны, а не по возрастанию идти. Надо глянуть в стандарт.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108080
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivНа самом деле скорее всего оба варианта кода, старый и новый, невалидны, потому что значения enum должны быть по стандарту уникальны, а не по возрастанию идти. Надо глянуть в стандарт.
enum не должны быть уникальны. Они по умолчанию всегда идут с нуля по возрастанию на 1.
Оба варианты правильны:
C++03 7.2 Enumeration declarationsThe identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required. An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression. The constant-expression shall be of integral or enumeration type. If the first enumerator has no initializer, the value of the corresponding constant is zero. An enumerator-definition without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator by one.

[Example:
enum { a , b, c =0 };
enum { d, e, f=e+2 };
defines a, c, and d to be zero , b and e to be 1, and f to be 3. ]
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108100
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum class,

Отсюда вывод: Код валидный, но не смотря на его валидность - он бессмысленный и не верный.
Код: plaintext
1.
2.
3.
4.
enum T1 {
    a1, a2=0, a3=100, a4=0,
    a_count = 0
};

И усе. Никакого обхода ты уже не сделаешь.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108118
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl,

Да вообще нужно перечисление enum — сделай себе массив всех значений и всё, будет честнее. Или в вектор их.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108223
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Количество способов выстрелить себе в ногу увеличилось еще на один. Записал с блокнотик.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108254
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonКоличество способов выстрелить себе в ногу увеличилось еще на один. Записал с блокнотик.
Оно всегда было или только сейчас про enum узнали?
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108261
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owlenum class,

Отсюда вывод: Код валидный, но не смотря на его валидность - он бессмысленный и не верный.
Код: plaintext
1.
2.
3.
4.
enum T1 {
    a1, a2=0, a3=100, a4=0,
    a_count = 0
};

И усе. Никакого обхода ты уже не сделаешь.
Ну так почти любой код загадить можно.
Тоже самое может быть (значения не по порядку, не уникальные и т.д.) и с массивом всех значений, или вектором, или структурой с константами или что взамен enum вы предлагаете?

MasterZivWhite Owl,
Да вообще нужно перечисление enum — сделай себе массив всех значений и всё, будет честнее. Или в вектор их.
Честнее для тех кто не знает стандарт и может сомневаться в значениях enum.
В enum есть один плюс по сравнению с массивом и вектором - проверка наличия такой константы, например func(a10) - выдаст compile-time ошибку, а func(arr[10]) - не выдаст.
Помимо этого каждый элемент enum можно обозвать более выразительно, а каждый элемент массива - нет.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108297
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum class,

Плюсую. При правильном применении (как и все фичи С/С++) enum помогает.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108320
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum classНу так почти любой код загадить можно.
С точки зрения коня в вакууме. А с точки зрения реального мира это единственная альтернатива толпе дефайнов.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108379
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyenum class,

Плюсую. При правильном применении (как и все фичи С/С++) enum помогает.
Получается для нумерации в пределах одного модуля(DLL) больше подходит enum class без перегруженных операторов, т.к. их перегрузка фактически превращает его в обычный enum.
Либо ещё такие варианты.
Статический массив:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
enum class T1 {
    a1, a2, a3, a4,
    a_count
};

struct Tmy {
    Tmy() : a(T1::a_count) {}    
    Tmy(const T1 _a) : a(_a) { /* switch(a) { case... } */ }
    T1 a;
};

const Tmy arr[static_cast<size_t>(T1::a_count)] = {
    Tmy(T1::a1),
    Tmy(T1::a2),
    Tmy(T1::a3),
    Tmy(T1::a4)
};



Динамический массив:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
enum class T1 {
    a1, a2, a3, a4,
    a_count
};

struct Tmy {
    Tmy() : a(T1::a_count) {}    
    Tmy(const T1 _a) : a(_a) { /* switch(a) { case... } */ }
    T1 a;
};

vector<Tmy> func(size_t size_arr) {
    vector<Tmy> dyn_arr;
    #pragma unroll
    for(size_t i = 0; i < size_arr; ++i) dyn_arr.push_back(Tmy(static_cast<T1>(i)));
    return dyn_arr;
}

const vector<Tmy> arr = func(static_cast<size_t>(T1::a_count));



А если нужна сквозная нумерация по объектам из DLL с динамической ликновкой и поздним связыванием, то std::map со строковым или своим типом индекса.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108380
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется ввиду по объектам из множества DLL с динамической ликновкой и поздним связыванием.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108383
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
OoCcenum classНу так почти любой код загадить можно.
С точки зрения коня в вакууме. А с точки зрения реального мира это единственная альтернатива толпе дефайнов.
Это:
Код: plaintext
1.
2.
3.
4.
enum class T1 {
    a0, a1, a2, a3,
    a_count
};


тоже самое что это:
Код: plaintext
1.
2.
3.
4.
enum class T1 {
    a0 = 0, a1 = 1, a2 = 2, a3 = 3,
    a_count = 3
};


и тоже самое что это:
Код: plaintext
1.
2.
3.
4.
5.
class T1 { 
    public:
    static const int a0 = 0, a1 = 1, a2 = 2, a3 = 3,
    a_count = 3;
};


А как бы это выглядело из дефайнов?
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108398
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum classпропущено...А как бы это выглядело из дефайнов?
Наоборот. Например имеем флажки - набор непересекающихся битовых значений и масок для выделения их наборов. Все это сидит ввиде дефайнов....
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108401
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
OoCcenum classпропущено...А как бы это выглядело из дефайнов?
Наоборот. Например имеем флажки - набор непересекающихся битовых значений и масок для выделения их наборов. Все это сидит ввиде дефайнов....
Почему бы их не задать статическими константами структуры или вы используете для не пересекающихся битовых значений монотонное возрастание enum class?
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108418
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum classпропущено...
Почему бы их не задать статическими константами структуры или вы используете для не пересекающихся битовых значений монотонное возрастание enum class?
Можно и так. enum появился гораздо раньше и был единственной альтернативой дефайнам. Сейчас это его легаси. Но этим пользуются и нельзя говорить что это загаживание кода.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108453
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
OoCcenum classпропущено...
Почему бы их не задать статическими константами структуры или вы используете для не пересекающихся битовых значений монотонное возрастание enum class?
Можно и так. enum появился гораздо раньше и был единственной альтернативой дефайнам.
enum появился раньше чем struct?
Код: plaintext
1.
2.
3.
4.
struct T1 {
    static const int a0 = 0, a1 = 1, a2 = 2, a3 = 3,
    count = 4;
};



OoCcСейчас это его легаси. Но этим пользуются и нельзя говорить что это загаживание кода.
А вы про присвоение конкретных значений перечислениям. Это не является загаживанием.
Загаживание это я говорил про присваивание конкретных значений тем перечислениям, которые должны использовать дефолтную нумерацию.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108568
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Набросал упрощенный примерчик с использованием enum class внутри модулей DLL и использовании std::map в EXE для регистрации создателей объектов абстрактной фабрики.
Для статического массива DLL1 при увеличении перечислений помимо изменения класса Tmy1 необходима правка списка инициализации массива, причем в строгой последовательности с enum.

В DLL2 это решено раскруткой шаблонной функции. В принципе там можно было и std::vector использовать вместо std::map.

Кстати, как избавиться от явного указания параметров шаблона в специализированной функции?
Код: plaintext
1.
2.
template<>
inline void add2map<0, T1, shared_ptr<Tbase_creator>>(map<T1, shared_ptr<Tbase_creator> > &) { }



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <memory>
using namespace std;

// enum made shared just for an example
enum class T1 {
    a0, a1, a2, a3, a4, a5,
    a_count
};

// my abstract working class
struct Tbase {
    virtual ~Tbase() {}
    virtual size_t get_num() = 0;
};

// factory
struct Tbase_creator {
    virtual ~Tbase_creator() {}
    virtual shared_ptr<Tbase> create() const = 0;
};


// DLL 1 -------------------------------------
template<T1 _a>
struct Tmy1 : Tbase {
    Tmy1() : a(_a) { /* switch(a) { case... } */ }    
    virtual size_t get_num() { return static_cast<size_t>(a)*10; }
    T1 a;
};

template<T1 _a>
struct Tmy1_creator : Tbase_creator {
    virtual shared_ptr<Tbase> create() const { return make_shared<Tmy1<_a>>(); }
};

// array of creators in DLL 1
static const shared_ptr<Tbase_creator> arr1[] = // [static_cast<size_t>(T1::a_count)] =
{
    make_shared<Tmy1_creator<T1::a0>>(),
    make_shared<Tmy1_creator<T1::a1>>(),
    make_shared<Tmy1_creator<T1::a2>>(),
    make_shared<Tmy1_creator<T1::a3>>()
};

template <typename T, size_t N> size_t arr_size(T (&)[N]) { return N; }

const shared_ptr<Tbase_creator>* get_creators_dll_1(size_t &size_arr) {
    size_arr = arr_size(arr1);
    return arr1;
}


// DLL 2 -------------------------------------
template<T1 _a>
struct Tmy2 : Tbase {
    Tmy2() : a(_a) { /* switch(a) { case... } */ }    
    virtual size_t get_num() { return static_cast<size_t>(a)*100; }
    T1 a;
};

template<T1 _a>
struct Tmy2_creator : Tbase_creator {
    virtual shared_ptr<Tbase> create() const { return make_shared<Tmy2<_a>>(); }
};


// unroll function of emplace
template<size_t N, typename Ti, typename Tv>
inline void add2map(map<Ti, Tv> &val) { 
    val[static_cast<Ti>(N-1)] = make_shared<Tmy2_creator<static_cast<Ti>(N-1)>>();
    //val.emplace_hint(val.end(), static_cast<Ti>(N-1), make_shared<Tmy2_creator<static_cast<Ti>(N-1)>>());
    add2map<N-1, Ti, Tv>(val);     
}

template<>
inline void add2map<0, T1, shared_ptr<Tbase_creator>>(map<T1, shared_ptr<Tbase_creator> > &) { }

template<T1 count, typename Ti, typename Tv>
inline map<Ti, Tv> func() {
    map<Ti, Tv> map_arr;
    add2map<count>(map_arr);    
    return map_arr;
}

// array of creators in DLL 2
const map<T1, shared_ptr<Tbase_creator>> arr2 = func<T1::a_count, T1, shared_ptr<Tbase_creator>>();

const map<T1, shared_ptr<Tbase_creator>> get_creators_dll_2() {
    return arr2;
}


// EXE -------------------------------------
map<string, shared_ptr<Tbase_creator>> arr3;

template<typename T>
string any2str(T val) {
    stringstream stream;
    stream << val;
    return stream.str();
}

int main() {

    shared_ptr<Tbase> a1_obj = arr1[static_cast<size_t>(T1::a1)]->create();
    cout << a1_obj->get_num() << endl;

    shared_ptr<Tbase> a2_obj = arr2.at(T1::a2)->create();
    cout << a2_obj->get_num() << endl;
    cout << endl; 
    
    // get all creators from all DLLs
    // DLL 1
    size_t size_arr = 0;
    const decltype(get_creators_dll_1(size_arr)) &temp_arr1 = get_creators_dll_1(size_arr);
    for(size_t i = 0; i < size_arr; ++i) {  
        string name_obj = "DLL1: " + any2str(any2str(i));
        arr3[name_obj] = temp_arr1[i];
    }    

    // DLL 2
    const decltype(get_creators_dll_2()) &temp_arr2 = get_creators_dll_2();
    for(decltype(temp_arr2.cbegin()) it = temp_arr2.cbegin(); it != temp_arr2.cend(); ++it) {  
        string name_obj = "DLL2: " + any2str(any2str(static_cast<size_t>(it->first)));
        arr3[name_obj] = it->second;
    }
    cout << endl;
    
    // create all objects
    for(decltype(arr3.begin()) it = arr3.begin(); it != arr3.end(); ++it) {
        shared_ptr<Tbase> a3_obj = it->second->create();
        cout << it->first << " : " << a3_obj->get_num() << endl;    
    }
    
//    shared_ptr<Tbase> a3_obj = arr3["3"]->create();
//    cout << endl << a3_obj->get_num() << endl;   
    return 0;
}
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108688
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum classНабросал упрощенный примерчик с использованием enum class внутри модулей DLL

А при чём тут DLL ? Enum работает одинаково как в DLL , так и без них.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108696
enum class
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivenum classНабросал упрощенный примерчик с использованием enum class внутри модулей DLL

А при чём тут DLL ? Enum работает одинаково как в DLL , так и без них.
Для примера, чтоб не в воздухе висел, а к конкретной задаче.
...
Рейтинг: 0 / 0
Обход enum class в C++11
    #38108803
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
enum classMasterZivпропущено...


А при чём тут DLL ? Enum работает одинаково как в DLL , так и без них.
Для примера, чтоб не в воздухе висел, а к конкретной задаче.

Ну, можно было бы там TCP-сокеты ещё приплести, для примера ....
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Обход enum class в C++11
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]