[[lifetimebound]]



В компиляторы C++ потихоньку приходят интересные фичи с memory safety, в этот раз поговорим о [[clang::lifetimebound]]. Он предназначен для того, чтобы показать, что жизнь возвращаемого объекта может зависеть от жизни аргумента



Я частенько видел код в духе



const std::string& s = StatusOrProtobuf()->field_value();



Где StatusOrProtobuf возвращает absl::StatusOr<Proto>, где мы знаем, что статус будет всего OkStatus.



И в этот момент я всегда задавался вопросом, а верно ли, что это просто неправильно? StatusOrProtobuf() будет же локальной переменной, в итоге мы берем ссылку на объект внутри локальной переменной, что вроде бы undefined behavior, так как локальная переменная разрушится.



Компиляторы и санитайзеры могут это не поймать так как примеры могут быть более интересными в духе





template<typename T, typename U>

const U &get_or_default(const std::map<T, U> &m,

const T &key,

const U &default_value);



В итоге если вернётся default value, то писать в духе



const std::string &val = get_or_default(m, "foo"s, "bar"s);



некорректно. В тестах можно забыть протестировать default_value, а в проде выстрелит.



В clang привнесли атрибут [[clang::lifetimebound]], который находит всякие такие баги на этапе компиляции. Можно писать





template<typename T, typename U>

const U &get_or_default(const std::map<T, U> &m [[clang::lifetimebound]],

const T &key, /* note, not lifetimebound */

const U &default_value [[clang::lifetimebound]]);



Просто скажу, что мы в abseil облепились этими лайфтаймами и нашли сотню другую багов. Очень полезно даже для примитивных типов вроде unique_ptr::operator* и тд. Его можно ставить на аргументы функций и на функции класса пока.



Это достаточно полезно в любом месте, где у вас есть какой-нибудь контейнерный утиль, пользуйтесь.



Да, в Rust это встроено в язык, lifetimebound это упрощенный простой один lifetime 'a в Rust. За любой срач по Rust в коментах бан.



Привнести такой атрибут хотели давно в P0936 и очень долго пытаются починить всякие range based for.