Boost logo

Boost :

From: Mateusz Loskot (mateusz_at_[hidden])
Date: 2020-03-30 18:38:29


Hi,

We're adding move semantics to some of GIL classes [1]
and we'd like to receive feedback on the move-assignment operator
for the image class [2] (copied below) that we've worked out so far
if there are any major blunders to correct or gaps to fill for C++11
compliant implementation:

image& operator=(image&& img)
{
    if (this == std::addressof(img))
        return *this;

    auto const exchange_memory = [](image& lhs, image& rhs)
    {
        lhs._memory = boost::exchange(rhs._memory, nullptr);
        lhs._align_in_bytes = boost::exchange(rhs._align_in_bytes, 0);
        lhs._allocated_bytes = boost::exchange(rhs._allocated_bytes, 0);
        lhs._view = boost::exchange(rhs._view, image::view_t{});
    };

    constexpr bool pocma =
std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value;
    if (pocma)
    {
        // non-sticky allocator, can adopt the memory, fast
        destruct_pixels(this->_view);
        this->deallocate();
        this->_alloc = img._alloc;
        exchange_memory(*this, img);
    }
    else if (_alloc == img._alloc)
    {
        // allocator stuck to the rhs, but it's equivalent of ours, we
can still adopt the memory
        destruct_pixels(_view);
        this->deallocate();
        exchange_memory(*this, img);
    }
    else
    {
        // cannot propagate the allocator and cannot adopt the memory
        if (img._memory)
        {
            allocate_and_copy(img.dimensions(), img._view);
            destruct_pixels(img._view);
            img.deallocate();
            img._view = image::view_t{};
        }
        else
        {
            destruct_pixels(this->_view);
            this->deallocate();
            this->_view = view_t{};
        }
    }
    return *this;
}

One thing that is still missing is the noexcept with expression
evaluated based on something like this

template <class _Alloc>
using is_noexcept = std::conditional_t
<
    std::allocator_traits<_Alloc>::is_always_equal::value,
    _Equal_allocators,
    typename std::allocator_traits<_Alloc>::propagate_on_container_move_assignment::type
>;

but we there is no is_always_equal in C++11, so there are gaps to fill.

Any comments are appreciated.

[1] https://github.com/boostorg/gil/pull/457/
[2] https://github.com/boostorg/gil/blob/7d8df1c105e81070e30ef68ea7abb8e39111d6e5/include/boost/gil/image.hpp#L152-L200

Best regards,

-- 
Mateusz Loskot, http://mateusz.loskot.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk