Комментарии 17
А вот если бы еще и примеры кода были не в картинках, а текстом, то статья получилась бы еще лучше.
Более 10 лет разрабатывал на С++, и решал множество подобных задач. И пришел к тому, что лучшее решение подобных задач - решать их не на С++, а на чем-нибудь интерпретируемом.
Я сам периодически думаю, что не тем занимаюсь. Но в бОльших масштабах.
Мне, после таких историй, зачастую хочется переквалифицироваться в "пекаря маковых рогаликов", и не видеть клавиатуры совсем.
А сменить С++ на интерпретируемый язык - это полумера :)
В недрах Google для решения описанных в статье задач в свое время был рожден и с тех пор успешно (как мне кажется) развивается язык Go.
Было бы интересно узнать ответ на вопрос "зачем в 2024 пилить HTTP-сервисы на C++?"
Мне (в контексте этой статьи) приходят на ум такие варианты ответов:
Потому что можем (Яндекс как никак)
Потому что разработчики C++ есть (Яндекс как никак), а разработчиков на Go в требуемом количестве (и качестве) не хватает
На объемах и нагрузках Яндекса производительности Go не хватает
Поделитесь, пожалуйста. Если, конечно, это не служебная тайна.
Спасибо.
На 99% уверен в 2 варианте. Яндекс ВСЕ подстроил под C++ и банально строить инфраструктуру под Go - не вариант.
Правильный ответ - "Я не знаю".
У меня есть исторические инсайды, которые мне позволяют сделать некоторые предположения. И мои предположения - вариация на тему пункта 2.
Но достоверно я ту историю не знаю, а любой мой ответ может быть трактован как "официальная позиция", поэтому спекулировать и рассказывать свои предположения я тут не буду.
Задайте этот вопрос Антону Полухину, он должен знать наверняка.
А зачем потребовалась рукопашная работа с ID для типов при наличии std::type_index
?
Ну, есть два ответа: официальный и неофициальный.
Официальный: генерация id от 0 до N, и создание id только для используемых типов, дает много возможностей для использования "разреженных массивов" вместо классических контейнеров. До самого страшного варианта - использовать массив вместо честного подсчета хеша от type_info, и сравнения строк.
Неофициальный: потому что это клево.
decltype(auto)
чтобы вернуть по референсу в случае одного типа, и тупл ссылок по значению в случае нескольких типов?
При такой регистрации типа возможна очень нехорошая ситуация.
При сборке разных библиотек в каждой из них будет своя собственная последовательность индексов type_index, а при сборке приложения вообще другая.
Для примера можно реализовать foolib с методом
void foo ()
{
::std::cout << "double:" << type_index<double>::value() << ::std::endl;
::std::cout << "int:" << type_index<int>::value() << ::std::endl;
}
затем barlib с методом
void bar ()
{
::std::cout << "int:" << type_index<int>::value() << ::std::endl;
::std::cout << "double:" << type_index<double>::value() << ::std::endl;
}
а затем в тестовом приложении сделать так
void baz()
{
::std::cout << "string:" << type_index<::std::string>::value() << ::std::endl;
::std::cout << "vector<int>:" << type_index<::std::vector<int>>::value() << ::std::endl;
}
int main()
{
foo();
bar();
baz();
return 0;
}
и получить на выходе
double:0
int:1
int:0
double:1
string:0
vector<int>:1
Это справедливое замечание.
Более того, тот тест на метод gate::details::type_id::next()
закомментирован в нашем коде, потому что тесты могут запускаться в разном порядке, и если тест для registry
запустится раньше этого, то тест свалится.
Однако, этот индекс находится в неймспейсе details
, соответственно, никогда не используется "напрямую". Индекс типа никуда не передается, нигде не сохраняется, эту функцию самостоятельно вообще не стоит дергать.
А если использовать в разных библиотеках не саму функцию, а только registry
- он будет работать правильно. Да, он в каждом собраном объектнике будет ориентироваться на свое подмножество типов и индексацию, но каждый будет работать "верно". И все тесты для registry
, в каком бы порядке они не были запущены, сработают верно. Индексация - только вспомогательный внутренний инструмент, который позволяет реализовать registry
.
А если использовать в разных библиотеках не саму функцию, а только
registry
- он будет работать правильно.
Если передать из одной библиотеки registry
сформированный в другой, то из-за несоответствия индексов в storage
будет получен не тот вектор значений.
В представленном решении используется unordered_map<type_index, any>
. Если использовать std::type_index
или соответствующий hash_code
, то таких проблем не будет.
Техническая сторона интересная, но жаль, что изложение это подстрочник выступления, читать сложно
Как называется цветовая схема?
Полезные фичи С++ на примере организации пайплайна