- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
struct Base { virtual const char *getName() = 0; virtual ~Base() = default; };
struct SE_0 : Base { virtual const char *getName() override { return "SE_0"; } };
struct SE_1 : Base { virtual const char *getName() override { return "SE_1"; } };
struct SE_2 : Base { virtual const char *getName() override { return "SE_2"; } };
enum TypesEnum {
E__BEGIN = 0,
E_0 = E__BEGIN,
E_1,
E_2,
E__END
};
template<TypesEnum>
struct Registry {};
template<>
struct Registry<E_0> {
static constexpr const char *name = "The first type (SE_0)";
using type = SE_0;
};
template<>
struct Registry<E_1> {
static constexpr const char *name = "A second type (SE_1)";
using type = SE_1;
};
template<>
struct Registry<E_2> {
static constexpr const char *name = "And the last type (SE_2)";
using type = SE_2;
};
template<TypesEnum CurrentType>
std::unique_ptr<Base> createTypeImpl(const char *name)
{
if constexpr (CurrentType < E__END) {
if (strstr(Registry<CurrentType>::name, name)) {
return std::make_unique<typename Registry<CurrentType>::type>();
}
return createTypeImpl<static_cast<TypesEnum>(CurrentType + 1)>(name);
} else {
(void)name; // Silence 'unreferenced formal parameter' warning
return nullptr;
}
}
std::unique_ptr<Base> createType(const char *name)
{
return createTypeImpl<E__BEGIN>(name);
}
int main()
{
std::cout << "first type: " << createType("first type")->getName() << std::endl;
std::cout << "second type: " << createType("second type")->getName() << std::endl;
std::cout << "last type: " << createType("last type")->getName() << std::endl;
return EXIT_SUCCESS;
}
Упоролся.
https://ideone.com/c11fz4
gost 29.04.2020 15:14 # 0
bormand 29.04.2020 16:44 # +1
j123123 29.04.2020 18:05 # +1
jojaxon 29.04.2020 18:10 # 0
Но в Ди с рефлексией проще. Тупо перечислил в цикле все имена в модуле, нашел потомков Base и создал.
jojaxon 29.04.2020 18:13 # 0
guest8 29.04.2020 18:21 # −999
Needless 29.04.2020 21:19 # 0
Проклинаю васю
bormand 29.04.2020 19:11 # 0
Needless 29.04.2020 22:46 # 0
Но для того, чтобы в рантайме выбрать класс это и не нужно.
bormand 29.04.2020 18:17 # 0
BECEHHuu_nemyx 29.04.2020 18:21 # 0
bormand 29.04.2020 18:27 # +1
З.Ы. Где-то у меня был пример, который в зависимости от значения константы компилится либо как шаблон либо как операторы сравнения.
j123123 29.04.2020 18:52 # +3
> Most programming languages’ grammars fall into the category of Context-Free Grammar (CFG), or sometimes Context-Sensitive Grammar (CSG). What about C++? It turns out parsing C++’s grammar is literally undecidable. In other words, if you have a compiler that parses all valid C++ sources perfectly, you have solved the Halting Problem.
Для написания 100% корректного компилятора C++ надо решить проблему остановки. Какой багор )))
jojaxon 29.04.2020 18:57 # +1
MediumGovno 01.08.2021 10:48 # 0
guest8 29.04.2020 23:06 # −999
bormand 30.04.2020 09:50 # 0
j123123 30.04.2020 20:41 # +1
и так далее. Наверняка в каком-нибудь стандарте появится и такая поебень
bormand 30.04.2020 21:14 # 0
j123123 30.04.2020 21:20 # +1
или сделать using namespace my_namespace; и тогда просто@0%$( некаяхуйня )@0%$ писать можно. Это ж какой простор для творчества!
j123123 30.04.2020 21:28 # +1
Да, я знаю что можно в пределах какой-то одной функции/метода и пр. эту хуйню с юзингом сделать, но это не то.
bormand 30.04.2020 21:30 # 0
guest8 30.04.2020 21:31 # −999
BECEHHuu_nemyx 30.04.2020 21:48 # +1
j123123 30.04.2020 21:50 # +1
bormand 30.04.2020 21:50 # +1
bormand 30.04.2020 21:51 # 0
bormand 30.04.2020 21:53 # +2
Во! Я думаю теперь точно примут пропозал.
Ну и using std = default на случай если ты затёр std чем-то другим и теперь хочешь вернуть на место.
j123123 30.04.2020 21:58 # +1
Лучше сделать pop(n). Типа, если несколько раз перезатер, можно на столько-то раз откатиться.
using std = pop(2);
j123123 30.04.2020 22:03 # 0
Это вообще суть крестов, взять какую-нибудь тупую херню типа шаблонов, и раздуть ее до уровня маразма
bormand 30.04.2020 22:14 # +1
1024-- 01.05.2020 00:25 # 0
С этим препроцессором можно переиспользовать имена переменных, создавая микроскоупы. Там есть реализации для кода на C, Python или JS, можно добаалять свои.
BECEHHuu_nemyx 30.04.2020 22:21 # 0
1024-- 01.05.2020 00:20 # 0
j123123 07.01.2022 16:39 # 0
https://govnokod.ru/26283#comment518451
> Еще выяснилось, что я не итератор, а шаблон. Ну и черт с ним, подумал я.
bormand 29.04.2020 18:44 # 0
Needless 29.04.2020 21:14 # 0
Поправь меня, если чио: createTypeImpl просматривает пачку классов, проверяя вхождение строки в поле, и когда находит, возвращает другой связанный с ним класс?
Needless 29.04.2020 21:31 # 0
gost 29.04.2020 21:58 # 0
guest8 29.04.2020 22:03 # −999
gost 29.04.2020 22:22 # 0
guest8 29.04.2020 22:26 # −999
gost 29.04.2020 22:30 # 0
guest8 29.04.2020 22:32 # −999
gost 29.04.2020 22:38 # 0
guest8 29.04.2020 22:40 # −999
guest8 29.04.2020 22:06 # −999
BECEHHuu_nemyx 29.04.2020 22:08 # +1
gost 29.04.2020 22:20 # 0
Юзер вводит «first type» — создаётся объект типа «SE_0»; вводит «second type» — объект типа «SE_1» и так далее.
guest8 29.04.2020 22:26 # −999
gost 29.04.2020 22:35 # 0
guest8 29.04.2020 22:38 # −999
gost 29.04.2020 22:46 # 0
guest8 29.04.2020 22:42 # −999
gost 29.04.2020 22:45 # 0
guest8 29.04.2020 22:47 # −999
gost 29.04.2020 22:52 # 0
В скриптушне я бы просто сделал декоратор а-ля @register (выше пример), а вот с крестами проблемка выходит — сделать инициализацию рантайм-карты без явного перечисления типов и строк в createObjectByName() проблематично*.
*Можно, но заёбисто.
MAKAKA 29.04.2020 22:56 # +2
Самое страшное это писать одно и тоже знание в нескольких местах.
Потому в генерилке ты пишешь его ОДИН раз, а дальше оно само генерийет бойлерплейт где хоть 100500 раз это знание написино.
Когда я паршу текст -- я описываю грамматиики и потом лексы с бизонами за меня генерят код с говном
Ты пишешь парсер сетевого протокола. Это тоже самое.
Тебе нужно описание этого протокола в каком-то формате, где к каждому типу пакета привязан класс.
И геренилка кода, которая эту хуйню за тебя сгенерит.
ЗЫ: Я нагуглилъ
http://www.icsi.berkeley.edu/pubs/networking/binpacIMC06.pdf
https://github.com/zeek/binpac
gost 29.04.2020 23:01 # 0
guest8 29.04.2020 23:04 # −999
gost 29.04.2020 23:07 # 0
guest8 29.04.2020 23:09 # −999
guest8 29.04.2020 22:27 # −999
gost 29.04.2020 22:41 # 0
> Нативно такие штуки хорошо писать толко на скриптоговне: там это вообще всегда их коробки и хорошо работает
Подтверждаю.
guest8 29.04.2020 22:42 # −999
guest8 29.04.2020 22:31 # −999
gost 29.04.2020 22:39 # 0
Для дополнительного веселья надо забыть заэскейпить «..».
guest8 29.04.2020 22:41 # −999
bormand 30.04.2020 10:23 # 0
guest8 30.04.2020 10:39 # −999
Needless 29.04.2020 22:07 # 0
bormand 30.04.2020 10:00 # 0
guest8 30.04.2020 10:04 # −999
bormand 30.04.2020 10:09 # 0
guest8 30.04.2020 10:11 # −999
guest8 30.04.2020 12:07 # −999
guest8 30.04.2020 12:15 # −999
guest8 30.04.2020 15:00 # −999
guest8 30.04.2020 15:01 # −999
BECEHHuu_nemyx 30.04.2020 15:17 # 0
Кстати, машинисты метро иногда в шутку «Боингом» называют такой аппарат:
https://ru.wikipedia.org/wiki/81-717/714
Потому что 717.
1024-- 30.04.2020 16:22 # 0
Тогда
* в base можно добавить static base *pituxes[PITUXES]; static size_t pituxes_length = 0;
* в pituz<T> добавить статический pituz<T>::bagor, который делает
pituxes[pituxes_length++] = new T;
* в pituz<T> добавить виртуальную питушню pituz<T>::insert = \m -> m[тут взять имя класса у рттиуха] = this
* бормандов instances заполнять как map (flip insert m) pituxes.
То есть за счёт питушино-рекурсивного наследовательного паттерна прописать всем детям питушню для добавления себя в питухов на статическом этапе, а также - себя и своего имени в выбранную мапу, когда будет мапа. Когда статика отработает, и все питухи инициализируются, можно будет воспользоваться STL. В программе берём мапу и форычим питухов, прося их добавиться в мапу.
Тогда каждый новый питух должен только унаследоваться от pitux<новый питух>, и он ватоматически добавится куда надо.
bormand 30.04.2020 16:25 # 0
1024-- 30.04.2020 17:27 # 0
Я всё равно не чувствую весомости потери гибкости. Получать классы по именам надо не в каждом проекте, а вот чтобы ещё несколько разных групп было - вообще редкий вариант.
bormand 30.04.2020 16:29 # 0
1024-- 30.04.2020 16:51 # 0
Ну не знаю, можно тогда из pituxes нагенерировать новые питушни по вкусу.
Или сделать pituz<T, GROUP1 | GROUP3 | PITUXI> - какую-то битушню с группами, и автоматически распихивать по группам.
Хотя, я не знаю, зачем вообще весь этот пердолинг и какие подмножества питушни могут понадобиться.
> связный список
Как мне кажется, долговато кодить для статической питушни. да и массив - царская питушня.
Кстати, malloc может на этапе статический инициализации быть не готовым к работе?
bormand 30.04.2020 17:18 # 0
Плюс с мапой чётко и в одном месте видно, что именно используется. И ты получишь ошибку конпеляции если что-то из этого забыл запилить.
1024-- 30.04.2020 17:31 # 0
>И ты получишь ошибку конпеляции если что-то из этого забыл запилить.
Если я забуду добавить в мапу, ошибки компиляции не будет. Хотя классы будут потомками Base и всё такое.
В случае с наследованием от вореционизатора я либо сразу не буду потомком Base, и компиляцию прикроют, либо буду и потомком, и сяду в мапу.
gost 30.04.2020 17:50 # 0
bormand 30.04.2020 18:22 # 0
Да и про один файл - это миф. Один хер тест какой-нибудь добавлять.
guest8 30.04.2020 18:23 # −999
gost 30.04.2020 18:38 # 0
gost 30.04.2020 16:53 # 0
На этом этапе проблема. В крестах статических блоков инициализации (как в ЙАЖА, например) нетути, можно только городить ненадёжную и нестабильную питушню вроде «static auto huj = static_initialization_function()», но так возникают проблемы от порядка инициализации (я вот хз, например, будет ли инициализирован CRT на момент вызова static_initialization_function()) и до множественной инициализации (если разместить функцию в .h).
1024-- 30.04.2020 17:05 # 0
* массив metuxes не указателей, а просто объектов (чтобы без malloc и прочей питушни)
* bagor с помощью placement new раскатывает в metuxes объект creator<T> с виртуальным методом который создаёт и помещает unique_ptr<T> в выбранную мапу.
Думаю, у всех креаторов будет размер как у указателя на vtable, поэтому их можно будет перебирать по значению и вытягивать из массива питухов реинтерпрет питухом.
1024-- 30.04.2020 17:10 # 0
pituxes станет char metuxes[100500] и вообще может стать статик питухом у base_creator, bagor будет делать
gost 30.04.2020 17:44 # 0
Главный вопрос в том, как он это будет делать. Нормальных статических блоков-то не завезли, поэтому нам придётся дёргать этот код в рантайме, а для этого надо, опять же, проитерироваться по всем зарегистрированным creator<T>.
1024-- 30.04.2020 18:08 # 0
Так и будет base <|--- pituz<S0> <|--- S0.
У pituz<S0> будет статический экземпляр pituz<S0>::creator_for_creator, у которого в конструкторе будет
creator<T> имеет виртуальный метод для создания T.
Хотя, давай по новой.
Вместо него можно использовать
Эта питушня будет создавать unique_ptr на новый объект и складывать его в мапу your_map.
metuxes создать как простой массив указателей на функции типа void (*)(std::map<..., uniq...<Base>>&);
У pituz<T> будет статический экземпляр pituz<T>::creator_for_creator, у которого в конструкторе будет metuxes[metuxes_lenth++] = put_me<T>;
А дальше будет функция fill_your_map, которая будет брать metuxes и вызывать их на переданной мапе в нужном месте.
При создании нового класса надо будет наследовать его от pituz<этот класс> и всё.
А там, где нужна мапа - делать std::map<.....> m; fill_your_map(m);
Вроде всё упавшее снова разложил по полочкам.
jojaxon 30.04.2020 18:13 # 0
1024-- 30.04.2020 18:15 # 0
gost 30.04.2020 18:49 # 0
gost 30.04.2020 19:44 # 0
1. Статический член (в твоей нотации — creator_for_creator) не инициализируется, если к нему явно не обратиться.
2. Этот же самый код, собранный через «clang», падает с сегфолтом. «Gcc» и «MSVC» работают (но согласно первому пункту).
Собственно, как я и говорил в верхних комментах, статическая иницализация в крестах — говно ёбанное. То ли дело ЙАЖА.
bormand 30.04.2020 21:33 # +1
Которая из её форм? Надо ещё парочку добавить чтобы пофиксить.
guest8 30.04.2020 21:38 # −999
1024-- 01.05.2020 00:45 # 0
http://govnokod.ru/15263
Поэтому я предлагал изначально на всякий случай питушить в простой массив.
> что будет делать put_me()
Создавать объект и добавлять в бормандову мапу
> и как будет реализована createObject(string name)?
return instances.at(name);
где instances - бормандова питушня из второго комментария.
> А там, где нужна мапа - делать std::map<.....> m; fill_your_map(m);
std::map<.....> instances; fill_your_map(instances);
gost 01.05.2020 00:55 # 0
Дык в мапу надо добавлять не объект, а функцию, создающую объект.
> return instances.at(name);
Дык нужны не синглтоны, а обычные объекты.
> Есть опасение
Дык не опасение, а реальность — оно вообще нихрена не работает.
1024-- 01.05.2020 02:26 # 0
Тут предлагают вставить в BaseRegistrator<>
Если попердолить это выражение, компиляторы перестают выдавать предупреждение, а код всё ещё работает.
Перенёс пердолинг с STL и прочей питушнёю сложнее царского массива в main, как и планировал.
Правда, я что-то не то сделал, и код со string_view сломался - заменил на string.
Вот, в итоге заставил работать эту питушню:
https://wandbox.org/permlink/KBmYlLmfVWyInOxk
Из-за синглтонства пришлось unique_pitux заменить на shared_pitux, сделал поэтому вспомогательный pointer<T>
> надо добавлять не объект, а функцию, создающую объект.
Хорошо, не будем слушать восьмишка, это тоже можно: https://wandbox.org/permlink/WT9nQqCZJfBPhcIb
gost 01.05.2020 02:46 # 0
Со static_assert, впрочем, выглядит как крайне ненадёжный хак, который сломается в следующей мажорной версии. Именно поэтому я против «C++».
jojaxon 01.05.2020 02:16 # 0
and then just map me
till I can fill your registration
1024-- 01.05.2020 02:31 # 0
digitalEugene 10.01.2022 15:02 # 0