Здравствуйте, AlexRK, Вы писали:
EP>>Вручную выписывать каждый контейнер, а потом выписывать каждый вариант обхода, да ещё и следить за изменением списка типов не удобно. Вот как раз для автоматизации всего этого и используются библиотеки подобного рода (например Boost.Fusion или Hana).
ARK>Проблему понял, хотя связь с приведенным лямбдовым кодом не вполне уловил.
Внутри реализации например нужно обходить все эти контейнеры — для этого нужен специальный for_each.
А при push_back значения — нужно найти правильный контейнер. Причём хоть это всё и происходит в compile-time, но всё же желательно чтобы поиск был суб-линейным, здесь уже появляется потребность в специальных структурах данных.
В результате появляются библиотеки для работы с такими гетерогенными значениями включающие в себя алгоритмы, структуры данных и т.п. Приведённый код с лямбдами демонстрирует небольшой кусочек мозаики. Но прелесть этого кода/трюка в том, что раньше, в C++98 для реализации аналога потребовалось намного больше кода.
ARK>Лично я, не будучи программистом экстра-класса (хотя и знаком с функциональными приблудами), однозначно предпочел бы видеть в проекте три или четыре руками написанных контейнера с разными объектами, чем нечитаемый (как минимум, лично мной) вышеприведенный говнокод с лямбдами.
А его и не нужно читать, это библиотечный код. Пользователю же можно предоставить достаточно простой интерфейс:
int main()
{
poly_seq<int, double> seq;
for(int i=0; i!=3; ++i)
{
push_back(seq, i); // int
push_back(seq, i+0.1); // double
}
for_each(seq, [](auto x)
{
cout << x << endl;
});
}
// Output is:
0
1
2
0.1
1.1
2.1
ARK>Если же число разнотипных контейнеров велико, то я бы задумался о применении нормальной — читаемой — кодогенерации (не на С++).
Кодогенерация далеко не всегда удобна. Например в этом примере for_each может быть в разных местах, и его могут использовать для разных действий — придётся генерировать каждый вариант, и делать кодогенерационные склейки в каждом месте. Так это ещё простой пример — меняться может не только действие, но и алгоритм, и даже контейнер — тогда придётся генерировать каждую комбинацию, в каждом месте.
Да и сам кодогенерационный код и сложнее обычного и тяжелей в поддержке — происходит по сути низкоуровневая манипуляция строками. Одно дело нагенерировать классы по схеме, а другое реализовывать по сути те же самые шаблоны.
Страуструп, кстати, тоже думал что макросов хватит:
http://cpp-lang.io/30-years-of-cpp-bjarne-stroustrup/
People often forget that parameterized types were there from the start. I used a vector macro with the element type as a macro parameter from the earliest days and Cfront shipped with a <generic.h> header. For a couple of years, I thought macros would be enough to support generic programming. I was very wrong about that, but I was right about the need to parameterize types and functions with (other) types. The result became templates (1988).
Здравствуйте, lpd, Вы писали:
1>>И каких же базовых функций не хватает в связке C++11, Boost, Qt?
lpd>Boost еще надо прилинковать — но он не очень и нужен допустим. Qt предлагает средства для UI и работы с
lpd>Bluetooth, NFC и т.п., но эти средства скорее лишние для framework, зато вроде бы отсутствует HTTP. Не уверен, что в QT
lpd>достаточные для web-приложений модули для работы с Web.
Cписок модулей Qt, все там есть, и для работы с сетью и с БД и с xml, и с устройствами, проще перечислять чего там нету чем что там есть. Нехватает некоторых специализированных вещей, но это скорей проблема С++ а не Qt. Из фреймфорков в которых есть почти все можно еще упоминуть Poco.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте