Skip to content

[BUG] move-assignment operators defaulting to memberwise semantics makes it impossible to cleanup old value #475

Closed
@jbatez

Description

@jbatez

Consider a smart pointer type for IUnknown that automatically calls IUnknown::Release where appropriate:

ComPtr: type = {
    m_raw: *IUnknown;

    // ...

    operator=: (inout this, move that) = {
        // Take the raw pointer from `that` first.
        // If `&that == &this`, setting it to nullptr
        // first ensures we don't release it.
        new_raw := std::exchange(that.m_raw, nullptr);
        if m_raw { m_raw*.Release(); }
        m_raw = new_raw;
    }

    // ...
}

cppfront generates the following code for the move-assignment operator:

    auto ComPtr::operator=(ComPtr&& that) noexcept -> ComPtr& {
        m_raw = std::move(that).m_raw;
        // Take the raw pointer from `that` first.
        // If `&that == &this`, setting it to nullptr
        // first ensures we don't release it.
        auto new_raw {std::exchange(std::move(that).m_raw, nullptr)}; 
        if (m_raw) {CPP2_UFCS_0(Release, (*cpp2::assert_not_null(m_raw))); }
        m_raw = std::move(new_raw);
        return *this;
    }

cppfront inserted m_raw = std::move(that).m_raw; before my code, meaning there's no way for me to call Release() on the old value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions