Класс Generi c, позволяющий выполнять резервное копирование / восстановление значений объектов - PullRequest
0 голосов
/ 01 апреля 2020

В стандартной библиотеке уже есть какое-либо средство, которое позволяет мне определять объект типа 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
...