В стандартной библиотеке уже есть какое-либо средство, которое позволяет мне определять объект типа T
, значение которого может быть зарезервировано и восстановлено?
Я думаю о чем-то вроде этого:
namespace detail
{
template<bool b>
using bool_constant = std::integral_constant<bool, b>;
template<typename T, typename... Args>
void construct_in_place(T& obj, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
{
::new (const_cast<void*>(static_cast<void const volatile*>(std::addressof(obj))))
T(std::forward<Args>(args)...);
}
} // namespace detail
template<typename T>
class restoreable
{
public:
template<class = std::enable_if_t<std::is_default_constructible_v<T>>>
restoreable() {}
template<typename... Args,
class = std::enable_if_t<std::is_constructible_v<T, Args...>>>
constexpr explicit restoreable(std::in_place_t, Args&&... args)
: m_value(std::forward<Args>(args)...)
{}
template<typename U>
using allow_direct_conversion = detail::bool_constant<
std::is_constructible_v<T, U>
&& !std::is_same_v<std::decay_t<U>, std::in_place_t>
&& !std::is_same_v<std::decay_t<U>, restoreable>>;
template<typename U = T, std::enable_if_t<std::conjunction_v<
allow_direct_conversion<U>,
std::is_convertible<U, T>>, int> = 0>
constexpr restoreable(U&& value)
: m_value(std::forward<U>(value))
{}
template<typename U = T, std::enable_if_t<std::conjunction_v<
allow_direct_conversion<U>,
std::negation<std::is_convertible<U, T>>>, int> = 0>
constexpr explicit restoreable(U&& value)
: m_value(std::forward<U>(value))
{}
template<typename... Args>
T& emplace(Args&&... args)
{
detail::construct_in_place(m_value, std::forward<Args>(args)...);
return m_value;
}
void backup() { m_backup = m_value; }
void restore() { m_value = m_backup; }
constexpr T& value() & { return m_value; }
constexpr T const& value() const& { return m_value; }
constexpr T&& value() && { return std::move(m_value); }
constexpr T const&& value() const&& { return std::move(m_value); }
private:
T m_backup, m_value;
}; // class restoreable