Comments 19
auto read ( FileName file_name );
auto read ( Url url );
За такую кодяру нужно по рукам бить. Сиди потом, разбирайся, что такое FileName, а что такое Url.
Подход strong typedef к простой декларации новых типов на основе существующих известен достаточно давно и имеет свою реализацию, например, в Boost.
Здесь показана возможность реализации такого подхода с помощью "умной" обертки на основе примера из доклада на коференции CppCon 2018.
И FileName и Url являются отдельными типами, а не синонимами. В этом весь смысл.
это очень известный паттер, который поддерживает множество авторитетных людей в языке, включая Страуструпа
например, есть масса единиц измерения: метры, килограммы, секунды и так далее. и он все могут представлены как float (или там double)
и такого рода подходы позволяют полностью отследить корректность этих единиц во всей программе, что спасает от большого количества разных ошибок
Ага, а потом рыцарь ордена битья рук линейкой пишет что-нибудь вроде:
void set_duration(int first_delay, int loop_duration);
И сиди потом разбирайся, в каких единицах параметр. И через год исправляй ошибки за кем-то, кто неглядя решил, что там секунды.
Я бы лучше написал миллисекунды, и если уж кому-нибудь станет интересно, что у этих миллисекунд под капотом, то пускай он как-нибудь наведёт курсор на имя типа, чтоб IDE ему показала определение.
Вы жестокий человек, если считаете нормальным по какому-то такому мелочному вопросу бить людей по рукам ?
del
for ( const auto & value : values )
cout << *&value << endl;
В чём смысл *&
?P.S. Кодстайл ужасный, читать очень тяжело. Чтобы отличить операторы от ссылок (
&
, &&
) и шаблонов (<
, >
), приходится вникать в семантику.(я не автор поста) По-моему, смысл & - создать временный объект ValuePointer, с вызовом guard в конструкторе и unguard в деструкторе. Ну а * - собственно взять завёрнутое в этот временный ValuePointer значение, но! - с дополнительными приспоблениями, реализованными в guard / unguard (ну, потоковая безопасность, что-то такое). Польза!
Конечно, невнимательный прикладной программист может случайно забыть добавить *& -- и не получить пользы. Код будет как бы работать, но не совсем: что-то крэшнется, что-то полетит не туда. Ну а кто сказал, что профессия программиста - простая и лёгкая? Программист должен быть внимательным!
Да и настолько неочевидное использование операторов это ужас какой-то. Это как на условный
++
повесить lock, а на --
unlock.А намёки на потокобезопасность встречаются только в примерах с
ThreadSafe::*
, так что непонятно, зачем в примере с простейшим случаем вообще какие-то guard'ы.Кодстайл ужасный, читать очень тяжело.
Совершенно согласен с таким утверждением. Однако, из многочисленных вариантов возможной реализации данный вариант оказался наиболее компактным и совместимым с использованием обычных типов.
В некоторых случаях имеется возможность реализации оператора неявного преобразования обертки к базовому типу, тогда код будет иметь привычный вид.
for ( const auto & value : values )
cout << value << endl;
Как раз над этим сейчас и работаю).
Если вы продолжаете работать над проектом, обратите, пожалуйста, внимание на правильность английского в идентификаторах, названиях файлов - IsXyzExists плохо звучит. Уберите.Is или замените на Does, убрав s на конце (DoesXyzExist).
если хочется, чтобы написанных код вызывал хоть какой-то интерес у сообщества, стоит
а) снабжать его максимально удобной и исчерпывающийся документацией на английском языке
б) полностью покрывать юнит тестами (которые, помимо всего прочего, выступают еще и хоть какими-то примерами использования библиотеки)
Если "потокобезопасность" это добавление на каждую операцию лока, то это не потокобезопасностьif(map.empty())
map.DO ANYTHING()
Это уже не потокобезопасный код, потенциальная гонка и всё прочее. Проще говоря таким способом невозможно сделать что то потокобезопасным, т.к. для этого нужно потокобезопасный интерфейс сам по себе.
Да и вообще невозможно на С++ сделать "strong typedef" универсальный в шаблоне. Этим будет невозможно пользоваться.
Ну и сложность гит проекта поражает(не в хорошем смысле) + нужно указывать, что вы используете нестандартные возможности(баги) языка типа loopholes
https://gitlab.com/ssoft-scl/module/model-kit/-/blob/master/src/Meta/Counter.h
Если "потокобезопасность" это добавление на каждую операцию лока, то это не потокобезопасность
Средства библиотеки позволяют сделать операцию lock, как на каждую операцию отдельно, так и на любой блок кода, в зависимости от желаний разработчика. На постоянной основе сейчас можно сделать блокировку так
using Map = Wrapper< map, ThreadSafe::RecursiveMutex >;
Map map;
void foo ()
{
// в месте, где нужен постоянный lock
auto map_ptr = ↦
// map_ptr - умный указатель, который выполнил lock
if ( map_ptr->empty() )
map_ptr->doAnything();
}
Добавляем дополнительные особенности реализации на C++ с помощью «умных» оберток