|
return (ptr ? *ptr : decltype(*ptr){std::forward<Default>(def)}); |
|
return (ptr ? *ptr : decltype(*ptr){}); |
Предполагаю, что в функции FindOrDefault без предоставленного default-а, если ключ отсутствует, намерением было возвращать default-constructed объект. Однако при создании объекта по форме T{} возможно попасть в случай, когда тип T не имеет default конструктора, но имеет конструктор от std::initializer_list. В этом случае поведение не будет соответствовать ожидаемому.
Пример: https://godbolt.org/z/TfxW1fY6s
Возможно правильным будет осуществлять инициализацию по форме T(), однако это приведёт к исчезновению агрегатной инициализации. Также, для единообразности вида и поведения, использовать T(std::forward<Default>(def)) для инициализации default значением (также исключить init-list-constructors).
При попытке осуществить это раскрывается вторая проблема. Тип decltype(*ptr) является ссылкой, а не значением. Поэтому при создании default результата в функциях FindOrDefault сперва инициализируется ссылка, которая затем используется для copy инициализации результата (https://eel.is/c++draft/expr.type.conv#1.3).
Пример: https://godbolt.org/z/eEvrMEfvM
userver/universal/include/userver/utils/algo.hpp
Line 60 in 8d7fb78
userver/universal/include/userver/utils/algo.hpp
Line 68 in 8d7fb78
Предполагаю, что в функции
FindOrDefaultбез предоставленного default-а, если ключ отсутствует, намерением было возвращать default-constructed объект. Однако при создании объекта по формеT{}возможно попасть в случай, когда типTне имеет default конструктора, но имеет конструктор отstd::initializer_list. В этом случае поведение не будет соответствовать ожидаемому.Пример: https://godbolt.org/z/TfxW1fY6s
Возможно правильным будет осуществлять инициализацию по форме
T(), однако это приведёт к исчезновению агрегатной инициализации. Также, для единообразности вида и поведения, использоватьT(std::forward<Default>(def))для инициализации default значением (также исключить init-list-constructors).При попытке осуществить это раскрывается вторая проблема. Тип
decltype(*ptr)является ссылкой, а не значением. Поэтому при создании default результата в функцияхFindOrDefaultсперва инициализируется ссылка, которая затем используется для copy инициализации результата (https://eel.is/c++draft/expr.type.conv#1.3).Пример: https://godbolt.org/z/eEvrMEfvM