Здравствуйте, rg45, Вы писали:
TB>>Я видел подходы boost, cereal, у тебя что-то подобное? R>Подходы boost и cereal — говно древнего мамонта. Нет, у меня совершенно другой принцип действия.
Так не томи уже.
boost::describe года 3 как вышел, не очень-то окаменеть успело. Хотя хз какой именно буст имеется в виду.
Здравствуйте, andrey.desman, Вы писали:
AD>Так не томи уже. AD>boost::describe года 3 как вышел, не очень-то окаменеть успело. Хотя хз какой именно буст имеется в виду.
Чтоб не затягивать интригу, опишу пока на словах. Подход основан на том, что структуры раскладываются при помощи structured binding. Следующий "финт ушами" — это построить констрейнт поверх structured binding. Ну а дальше дело техники: сначала делаем универсальный компайл-тайм визитор, позволяющий декомпозировать объект произвольной структуры в произвольную вызываемую сущность. Разумеется, вызов визитора также защищен констрейнтом. Ну а поверх этого уже можно делать и операторы, и сериализацию и т.д. и т.п. Вложенность структур поддерживается автоматом. Конечно же, такой подход дает доступ к значениям полей структуры, но не дает доступа к именам мемберов. Для бинарной сериализации этого вполне достаточно. Сериализацию в xml и json, для которых требуются сигнатуры полей, тоже можно костылить, в принципе, но сигнатуры придется как-то генерить.
Более-менее функциональный пример сказанного будет вечером.
Здравствуйте, Евгений Музыченко, Вы писали:
S>>Полагаю, не в C++
ЕМ>В том числе и в C++ — в VC++ есть __if_exists/__if_not_exists. Это, конечно, слабое подобие левой руки, да и реализовано было коряво, отчего им и пришлось неофициально (через Чена) объявить о нежелательности использования. Однако до сколько-нибудь явных ограничений не дошло и до сих пор.
Так это все даже в сочетании с if constexpr в C++ не дает простого способа наполнять шаблон класса в зависимости от того, что есть в параметрах шаблона.
Получается, что опыта нет.
S>>т.к. шаблонную магию в C++ вы принципиально не используете.
ЕМ>Не использую — пока у меня, по счастью, не возникало ситуаций, в которых ее использование объективно упростило бы жизнь. Очень надеюсь, что и не возникнет.
Евгений, без обид, но вы производите впечатление человека, который 30 лет долбит одну узкую тему обработки аудиопотоков в драйверах ОС Windows. Тема, наверняка сложная с кучей своей специфики. Но опыт ваш настолько ограничен и настолько далек от проблем, которые решаются на C++ вне вашей узкой специализации, что вот прям ой. Даже так: ой-ой-ой.
При этом вы беретесь судить о вещах, в которых явно не разбираетесь.
S>>как раз таки делал подобное в C++ (без особых проблем даже в рамках C++11/14)
ЕМ>Так я не говорил, что это невозможно. Я говорил, что в C++ это делается через задницу, в виде побочного эффекта от конструкций, изначально предназначенных для другого.
Вы напоминаете героя известного монолога, который сетует на то, что вчера раки были большие, но по пять.
Не знаю как вы, а я живу в мире, где история развилась вот так. И в C++ мы имеем то, что имеем. Сетовать на то, что история могла бы (или должна была бы) пойти не так можно, но бесполезно. Тогда как вы этим регулярно занимаетесь.
Здравствуйте, so5team, Вы писали:
S>Так это все даже в сочетании с if constexpr в C++ не дает простого способа наполнять шаблон класса в зависимости от того, что есть в параметрах шаблона.
О том и речь, что это все убогие костыли, как и if constexpr. Такое ощущение, что комитет поставил себе целью растянуть окультуривание языка минимум до 2050-го года, добавляя функциональность по чайной ложке. А восторгов каждый раз столько, будто новый язык выкатили.
S>вы производите впечатление человека, который 30 лет долбит одну узкую тему обработки аудиопотоков в драйверах ОС Windows.
Не только в драйверах, и не только аудиопотоков, но за то, что требует использования современных стилей и/или библиотек, не берусь — мне нервы дороже.
S>опыт ваш настолько ограничен и настолько далек от проблем, которые решаются на C++ вне вашей узкой специализации, что вот прям ой.
Вы это уже в который раз подаете так, будто на C++ решаются какие-то сверхъестественные задачи, недоступные моему пониманию. Что такого можно "решать на C++", чтобы это принципиально, качественно отличалось от той же обработки аудиопотоков?
S>При этом вы беретесь судить о вещах, в которых явно не разбираетесь.
Это Вы о чем конкретно?
S>я живу в мире, где история развилась вот так. И в C++ мы имеем то, что имеем.
Осталось уточнить, что именно выражает эта фраза — примирение со сложившейся реальностью, или же утверждение, что имеем один из оптимальных вариантов.
S>Сетовать на то, что история могла бы (или должна была бы) пойти не так можно, но бесполезно.
Бесполезно это лишь в том случае, когда ход истории определяется в основном случайными факторами, и вероятность развития событий при любой развилке примерно одинакова, и наблюдение за реализованными вероятностями не дает возможность строить надежные прогнозы. В нашей ситуации это совершенно не так.
Здравствуйте, landerhigh, Вы писали:
L>Никто не планировал, что механизм шаблонов со своим sfinae внезапно позволит делать такие адские штуки прямо в compile time.
Да и ради бога, это вообще другая сфера применения. Но, заявив о возможности писать универсальный код, в который могут подставляться разные типы, следует сразу же подумать о средствах настройки такого кода. Иначе получается нечто вроде C, в котором есть типы разного размера, но нет sizeof, поэтому для каждого типа нужно явно определять размер макросом.
L>С точки зрения инженера — используется встроенная в язык фича, посему has_field получается вообще халявным. Короче — работает. Причем, искаропки. Причем, соответствует стандарту.
А сумеете найти примеры подобного подхода в других сферах, где большинство инженеров признавало бы это адекватным решением?
L>А ты попробуй хотя бы черновик такого proposal написать
В чем именно Вы видите сложность — хоть написания proposal, хоть реализации?
Здравствуйте, Евгений Музыченко, Вы писали:
S>>Так это все даже в сочетании с if constexpr в C++ не дает простого способа наполнять шаблон класса в зависимости от того, что есть в параметрах шаблона.
ЕМ>О том и речь, что это все убогие костыли, как и if constexpr.
Где не костыли?
S>>опыт ваш настолько ограничен и настолько далек от проблем, которые решаются на C++ вне вашей узкой специализации, что вот прям ой.
ЕМ>Вы это уже в который раз подаете так, будто на C++ решаются какие-то сверхъестественные задачи, недоступные моему пониманию. Что такого можно "решать на C++", чтобы это принципиально, качественно отличалось от той же обработки аудиопотоков?
Как бы это вам помягче объяснить. Ну представьте себе, что вы всю жизнь делали канализацию для двухэтажных коттеджей с одной кухней и двумя санузлами. Но при этом рассуждаете о проблемах организации канализации в гостиницах на 10000 номеров или небоскребах на 50+ этажей. Хотя, казалось бы, и там, и там, и там, говно с водой по трубам. Принципиально же то же самое.
Ага.
S>>При этом вы беретесь судить о вещах, в которых явно не разбираетесь.
ЕМ>Это Вы о чем конкретно?
Например, о том, с какими проблемами сталкиваются команды хотя бы в 10 человек на кодовой базе от 250KLOC.
S>>я живу в мире, где история развилась вот так. И в C++ мы имеем то, что имеем.
ЕМ>Осталось уточнить, что именно выражает эта фраза — примирение со сложившейся реальностью, или же утверждение, что имеем один из оптимальных вариантов.
Во-первых, то, что давать оценки оптимальности того что есть имеет смысл если вы пытаетесь сделать лучше. Вы пытаетесь сделать конкурента C++?
Во-вторых, мне не нужно примеряться со сложившейся реальность. Я с ней и не сорился. Есть что есть и моя задача научиться этим пользоваться.
ЕМ>Бесполезно это лишь в том случае, когда ход истории определяется в основном случайными факторами, и вероятность развития событий при любой развилке примерно одинакова, и наблюдение за реализованными вероятностями не дает возможность строить надежные прогнозы.
Здравствуйте, Евгений Музыченко, Вы писали:
L>>Никто не планировал, что механизм шаблонов со своим sfinae внезапно позволит делать такие адские штуки прямо в compile time. ЕМ>Да и ради бога, это вообще другая сфера применения. Но, заявив о возможности писать универсальный код, в который могут подставляться разные типы, следует сразу же подумать о средствах настройки такого кода. Иначе получается нечто вроде C, в котором есть типы разного размера, но нет sizeof, поэтому для каждого типа нужно явно определять размер макросом.
Опять же, задним числом все умны. Что ж сразу как надо не сделали?
L>>С точки зрения инженера — используется встроенная в язык фича, посему has_field получается вообще халявным. Короче — работает. Причем, искаропки. Причем, соответствует стандарту. ЕМ>А сумеете найти примеры подобного подхода в других сферах, где большинство инженеров признавало бы это адекватным решением?
Это не подход. Это ключевой принцип прогресса.
Невозможно сразу сделать идеально. Хотя бы потому, что критерии этого "идеально" появляются только после того, как сделали хоть как-нибудь. Опять же, пример с SMS — никто всерьез и не мог представить, что народ будет общаться короткими сообщениями, он появился по остаточному принципу и вообще изначально, скорее всего, предполагался для доставки исключительно служебных сообщений.
Вот стек протоколов IEC61850 — это просто лютый 3.14, пардон май френч. Но если посмотреть на то, когда его начали разрабатывать, становится более-менее понятно, почему именно такая херня вышла. Могло быть и сильно хуже.
L>>А ты попробуй хотя бы черновик такого proposal написать ЕМ>В чем именно Вы видите сложность — хоть написания proposal, хоть реализации?
Мы писали tissues в означенный протокол. Это сцуко адовая работа.
Здравствуйте, andrey.desman, Вы писали: AD>Так не томи уже. AD>boost::describe года 3 как вышел, не очень-то окаменеть успело. Хотя хз какой именно буст имеется в виду.
В общем, пацаны, жестокий облом у меня случился, сильно не бейте. Вот текст примера (просто чтоб не подумали, что я тут сочинял что-то):
Скрытый текст
#include <array>
#include <iostream>
#include <string>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repeat_from_to.hpp>
struct
{
#define DEFINE_STRUCT_VISITOR_OPERATOR(_, N, __) \
template <typename T, typename F> \
requires requires{[](T&& t, F&& f) { \
auto&& [BOOST_PP_ENUM_PARAMS(N, f_)] = t; \
return f(BOOST_PP_ENUM_PARAMS(N, f_)); \
};} \
constexpr decltype(auto) operator()(T&& t, F&& f) const { \
auto&& [BOOST_PP_ENUM_PARAMS(N, f_)] = t; \
return f(BOOST_PP_ENUM_PARAMS(N, f_)); \
}
BOOST_PP_REPEAT_FROM_TO(1, 51, DEFINE_STRUCT_VISITOR_OPERATOR, )
#undef DEFINE_STRUCT_VISITOR_OPERATOR
} inline constexpr VisitStruct;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Use cases
// Formatted structure printing
decltype(auto) PrintStruct(auto&& o, const auto& t, const auto&...x)
{
o << "{" << t;
((o << "," << x),...);
o << "}";
return o;
}
template <typename T, typename O>
concept PrintableStruct = requires (T t, O o) { VisitStruct(t, [&o](auto&&...x) {PrintStruct(o, x...); }); };
template <typename O>
O&& operator << (O&& o, const PrintableStruct<O> auto& t)
{
VisitStruct(t, [&o](auto&&...x){PrintStruct(o, x...);});
return std::forward<O>(o);
};
// Просто определяем структуру.
// Оператор вывова в поток определяется автоматически :)struct Foo
{
int i{};
double d{};
std::string s;
};
int main()
{
// Структуры могут быть локальными и даже анонимными.
// Структуры могут агрегировать другие структуры, массивы и кортежиstruct
{
int a = 1, b = 2, c = 3;
std::array<int, 3> a2 = {100, 200, 300};
Foo a3[3] = {{42, 3.14, "Hello"}, {123, 2.71, "World"}, {555, 1.61, "Hello, World"}};
struct
{
int i{};
double d{};
const char* s;
} s = {777, 1.23, "C++20"};
} bar;
std::cout << bar << std::endl;
}
Этот пример работает на msvc, но не работает на gcc. Причем, не работает как раз вот тот самый "финт ушами", о котором я упоминал здесь
. gcc вместо того, чтобы продетектить невалидность выражения внутри констрейнта, с какого-то перепуга начинает диагностировать ошибки в этом выражении. Для меня такое поведение очень странно. Я с этим еще буду разбираться. Было бы здорово, если бы кто-нибудь посмотрел этот пример, особенно на код VisitStruct, возможно, будут идеи, как это можно усовершенствовать.
Здравствуйте, reversecode, Вы писали:
R>ну так boost::pfr полухин изобрел и добавил R>доклада не вспомню R>но он показывал как просто выглядит сериализация после этого
Здравствуйте, so5team, Вы писали:
ЕМ>>О том и речь, что это все убогие костыли, как и if constexpr.
S>Где не костыли?
Из современных — не знаю, давно не интересовался. Из старых — в макроассемблерах, в PL/1, вроде как в Algol-68 тоже.
S>Как бы это вам помягче объяснить. Ну представьте себе, что вы всю жизнь делали канализацию для двухэтажных коттеджей с одной кухней и двумя санузлами. Но при этом рассуждаете о проблемах организации канализации в гостиницах на 10000 номеров или небоскребах на 50+ этажей. Хотя, казалось бы, и там, и там, и там, говно с водой по трубам. Принципиально же то же самое.
Принципиально там делается так же, различия в основном количественные (диаметр и толщина стенок труб, обеспечение уклонов, сглаживание перепадов давления и т.п.). Если знаете какие-нибудь качественные отличия — укажите, обсудим.
S>Например, о том, с какими проблемами сталкиваются команды хотя бы в 10 человек на кодовой базе от 250KLOC.
С какими конкретно проблемами сталкиваются такие команды, что замена шаблонной магии на более адекватные средства, встроенные в компилятор, могли бы эти проблемы усугубить?
S>Вы пытаетесь сделать конкурента C++?
Нет, я лишь удивляюсь, почему некоторые вещи на C++ принято делать через задницу, когда их можно было бы делать гораздо более прямо, логично, эффективно и надежно.
S>Есть что есть и моя задача научиться этим пользоваться.
Я уже приводил пример с sizeof. Если бы в C его не было вообще, и размеры типов приходилось бы определять явно, а в C++ его тоже не стали бы вводить, предлагая определять вместо макросов специализации шаблонов — Вы тоже безропотно "учились бы пользоваться"?
Здравствуйте, landerhigh, Вы писали:
L>задним числом все умны.
Я уже пояснял, что это возражение годится для других случаев, а сюда — не особо.
L>Что ж сразу как надо не сделали?
Скорее всего, сперва казалось, что не очень-то и нужно, а потом увидели, что народ наловчился чесать левую пятку через правое плечо, и подумали, что нехай и дальше так будет. Немалое влияние оказало то, что в эпоху постмодернизма шаблонная магия многими воспринимается, как нечто высокое, в противовес банальным встроенным средствам. Примерно так же стараются без нужды всунуть рекурсию вместо цикла, чтоб выглядело небанально.
L>Это не подход. Это ключевой принцип прогресса.
Э-э-э... Точно ли ключевой?
L>Невозможно сразу сделать идеально.
Да при чем тут идеал-то? Можно было сделать адекватно, как это уже много раз делалось раньше для других языков.
L>пример с SMS — никто всерьез и не мог представить, что народ будет общаться короткими сообщениями
С чего Вы это взяли? До SMS народ двести лет общался телеграммами, и мечтал о возможности делать это без похода в специальные учреждения.
L>он появился по остаточному принципу
Где Вы вычитали такую глупость? Судя по всему, Вам никогда не приходилось диктовать по телефону тексты.
L>Вот стек протоколов IEC61850 — это просто лютый 3.14, пардон май френч. Но если посмотреть на то, когда его начали разрабатывать, становится более-менее понятно, почему именно такая херня вышла. Могло быть и сильно хуже.
Со стандартами "всеобщего" характера, которые нужно разработать и принять сейчас, не зная толком, как они будут применяться и развиваться впоследствии, почти всегда так получается. У нас совершенно не тот случай — средства метапрограммирования (шаблоны) уже были придуманы и реализованы, и уже было понятно, какую информацию из шаблона придется хранить компилятору. Осталась самая малость — обеспечить возможность добыть эту информацию из компилятора. Даже если в первые годы еще не было очевидно, какая именно информация потребуется чаще, а какая реже, потом-то что мешало все эти type traits перенести в язык?
L>Мы писали tissues в означенный протокол. Это сцуко адовая работа.
Вот какая связь именно с означенным протоколом? Вы еще скажите, что, коли сложно написать багрепорт на редкие глюки многопоточного кода, работающего со внешними событиями, то и багрепорт на однопоточный код, обрабатывающий статический текст, писать настолько же сложно.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я уже пояснял, что это возражение годится для других случаев, а сюда — не особо.
Вот сразу ниже:
ЕМ>Скорее всего, сперва казалось, что не очень-то и нужно, а потом увидели, что народ наловчился чесать левую пятку через правое плечо, и подумали, что нехай и дальше так будет. Немалое влияние оказало то, что в эпоху постмодернизма шаблонная магия многими воспринимается, как нечто высокое, в противовес банальным встроенным средствам. Примерно так же стараются без нужды всунуть рекурсию вместо цикла, чтоб выглядело небанально.
Вот это и есть "задним числом".
L>>Это не подход. Это ключевой принцип прогресса. ЕМ>Э-э-э... Точно ли ключевой?
Почти двигатель, да.
L>>Невозможно сразу сделать идеально. ЕМ>Да при чем тут идеал-то? Можно было сделать адекватно, как это уже много раз делалось раньше для других языков.
А может быть, рефлексия в плюсах вообще не рассматривалась как что-то необходимое?
L>>пример с SMS — никто всерьез и не мог представить, что народ будет общаться короткими сообщениями ЕМ>С чего Вы это взяли? До SMS народ двести лет общался телеграммами, и мечтал о возможности делать это без похода в специальные учреждения.
L>>он появился по остаточному принципу ЕМ>Где Вы вычитали такую глупость?
Давным-давно я писал декодеры протоколов для GSM анализаторов.
Так вот, SMS просто впихнули в "дырку", оставшуюся между пейлоадом одного и фреймом другого протокола. Вот в упор не помню, как они назывались, да и неважно, сегодня эти протоколы уже история. То есть буквально "у нас тут 140 байт бесхозных, давайте их как-то задействуем". В некоторых очень старых спеках я даже видел упоминание стандартных сообщений и пиктограмм, которые можно было бы использовать через таблицу кодов — смс-ки, возможно, задумывались более как технические сообщения от провайдера к юзеру. Следует иметь в виду, что в первых мобилах текстовая клавиатура вообще не предусматривалась.
L>>Вот стек протоколов IEC61850 — это просто лютый 3.14, пардон май френч. Но если посмотреть на то, когда его начали разрабатывать, становится более-менее понятно, почему именно такая херня вышла. Могло быть и сильно хуже.
ЕМ>Со стандартами "всеобщего" характера, которые нужно разработать и принять сейчас, не зная толком, как они будут применяться и развиваться впоследствии, почти всегда так получается. ЕМ>У нас совершенно не тот случай — средства метапрограммирования (шаблоны) уже были придуманы и реализованы,
У нас тут совершенно тот же самый случай. Шаблоны разрабатывались как средство обобщенного программирования, но их реализация в плюсах позволила делать еще и шаблонную магию.
ЕМ>и уже было понятно, какую информацию из шаблона придется хранить компилятору.
И какая информация из шаблона, которую хранит компилятор, помогает узнать, есть у типа метод или нет?
L>>Мы писали tissues в означенный протокол. Это сцуко адовая работа. ЕМ>Вот какая связь именно с означенным протоколом?
Связь самая прямая. Написать tissue просто на один баг — это уже адов труд. Причем, tissue мы писали по поводу неоднозначности одной-единственной формулировки, которая позволяла двоякое толкование, и, как результат — несовместимые реализации. По сути мы предгалали просто исправить одно предложение в одной PDF-ке
Так вот, предлагаю хотя бы попытаться написать proposal. Чтобы в нем ни одно предложение не могло быть истолкованно неправильно.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Из современных — не знаю
Ясно-понятно.
S>>Как бы это вам помягче объяснить. Ну представьте себе, что вы всю жизнь делали канализацию для двухэтажных коттеджей с одной кухней и двумя санузлами. Но при этом рассуждаете о проблемах организации канализации в гостиницах на 10000 номеров или небоскребах на 50+ этажей. Хотя, казалось бы, и там, и там, и там, говно с водой по трубам. Принципиально же то же самое.
ЕМ>Принципиально там делается так же, различия в основном количественные (диаметр и толщина стенок труб, обеспечение уклонов, сглаживание перепадов давления и т.п.). Если знаете какие-нибудь качественные отличия — укажите, обсудим.
Качественные отличия -- это взять и сделать. Опыта взять и сделать в другом масштабе у вас просто нет. Но мнение имеете. Вот, собственно, и главная причина пускать ваши рассуждения в /dev/null по умолчанию.
S>>Например, о том, с какими проблемами сталкиваются команды хотя бы в 10 человек на кодовой базе от 250KLOC.
ЕМ>С какими конкретно проблемами сталкиваются такие команды, что замена шаблонной магии
Вы ругаете программирование на шаблонах не представляя себе как эти средства используются в других условиях. При этом у вас нет опыта и знаний о том, какими же "более адекватными средствами" их можно заменить. Т.е. у вас нет ни представления о проблемах, ни идей о том, как их устранить, ни современного опыта применения каких-либо механизмов из других ЯП.
Т.е. вы просто вышли позвиздеть о том, как могло бы быть если бы у истории было бы сослагательное наклонение.
S>>Вы пытаетесь сделать конкурента C++?
ЕМ>Нет
Тогда все, разговор закончен. Для упрощения жизни C++ разработчикам вы можете сделать ничего.
S>>Есть что есть и моя задача научиться этим пользоваться.
ЕМ>Я уже приводил пример с sizeof.
Вы еще приводили пример с отсутствием указателя на функцию в Ada.
ЕМ>Вы тоже безропотно "учились бы пользоваться"?
Вот в C++98 не было static_assert и да, приходилось учиться делать оный из подручных средств.
Здравствуйте, rg45, Вы писали:
R>Этот пример работает на msvc, но не работает на gcc. Причем, не работает как раз вот тот самый "финт ушами", о котором я упоминал здесь
. gcc вместо того, чтобы продетектить невалидность выражения внутри констрейнта, с какого-то перепуга начинает диагностировать ошибки в этом выражении. Для меня такое поведение очень странно. Я с этим еще буду разбираться. Было бы здорово, если бы кто-нибудь посмотрел этот пример, особенно на код VisitStruct, возможно, будут идеи, как это можно усовершенствовать.
Тут gcc прав, а MSVC нет. Происходит примерно следущее (упростил):
#include <iostream>
template<typename T>
concept SomeConcept = requires(T t) {
[](T&& t){ auto&& [a, b, c] = t; };
};
struct Test {
int a, b;
};
int main() {
std::cout << SomeConcept<Test>;
return 0;
}
Что такое лямбда-выражение? Это prvalue какого-то класса, который объявлен в ближайшем скоупе. Таким образом, условно это разворачивается в следущий код:
Здравствуйте, Евгений Музыченко, Вы писали:
S>>Вы ругаете программирование на шаблонах
ЕМ>Вы меня с кем-то спутали. Я никогда не ругал программирования на шаблонах.
Основное, что сделали в C++11 — магию попросту замели под ковер (включили в состав std). В std она по-прежнему реализована на языке C++ — то есть, на его шаблонах. Это даже хуже, чем при обработке операции i++ подставлять из файлика текст сишной функции, возвращающей i+1. Стыдобища.
И это даже из данной темы никуда уходить не пришлось.
Никогда. Я ругаю исключительно шаблонную магию — извращенное использование шаблонов для реализации функций, не реализуемых языком по причине его убожества в сфере метапрограммирования.