Daily bit(e) C++. Ограничение noexcept
Добавлено 17 марта 2024 в 23:11
Daily bit(e) 439. Поддержка ограничивающего кода noexcept
с помощью концептов C++20.
Реализация обобщенного кода C++ может быть сложной, поскольку любая операция потенциально может выкинуть исключение.
Примечательно, что, когда требуется строгая гарантия исключений, это может значительно усложнить код и привести к накладным расходам во время выполнения (или даже к изменению сложности «O большого»).
К счастью, для обеспечения соблюдения гарантий noexcept
во время компиляции концепты можно использовать C++20.
#include <utility>
struct UnsafeType
{
UnsafeType() = default;
UnsafeType(UnsafeType&&) {}
UnsafeType& operator=(UnsafeType&&) { return *this; }
};
template <typename T>
void unsafe_swap(T& left, T& right)
{
auto tmp = std::move(left);
left = std::move(right); // Что будет, если этот move выкинет исключение?
// было выполнено перемещение значения из left,
// и перемещение этого значения в right снова может выкинуть исключение
right = std::move(tmp);
}
struct SafeType
{
SafeType() = default;
SafeType(SafeType&&) noexcept {}
SafeType& operator=(SafeType&&) noexcept { return *this; }
};
template <typename T>
requires requires (T& a, T& b)
{
// присваивание перемещением допустимо и не выкидывает исключение
{ a = std::move(b) } noexcept;
}
void safe_swap(T& left, T& right)
{
auto tmp = std::move(left);
left = std::move(right);
right = std::move(tmp);
}
SafeType a, b;
safe_swap(a, b); // OK
UnsafeType x, y;
// Не скомпилируется:
// safe_swap(x, y);
// UnsafeType не удовлетворяет требованию noexcept