Pimpl и идиома копирования и обмена - PullRequest
0 голосов
/ 24 марта 2020

Я видел много вопросов и ответов относительно идиомы копирования и обмена (в сочетании с идиомой pimpl). Недавно я реализовал класс, используя оба, и в итоге получил несколько вопросов:

1 В случае класса с прыщами, нужна ли мне (по-прежнему) функция, не являющаяся другом swap (как описано в этот вопрос )? Поскольку вопрос уже 10 лет, есть ли какие-либо изменения в этом отношении?

2 В случае pimpl (основанного на уникальном ptr), стандартная std::swap не будет работать нормально? (В этом случае мне не нужен пользовательский своп)

3 У меня есть все члены в структуре pimpl. Если все копируемое, разве я не могу использовать конструктор копирования по умолчанию?

// trial.h
class Trial
{
public:
    Trial(ID a_ID = UNKNOWN_ID);
    Trial(const Trial& rhs);
    Trial(Trial&& rhs) noexcept;
    ~Trial();
    Trial& operator=(Trial rhs);

    void swap(Trial& rhs);
    inline ID GetID() const;

private:
    struct TrialImpl;
    std::unique_ptr<TrialImpl> m_Impl;
};

// trial.cpp
struct Trial::TrialImpl
{
    TrialImpl(ID a_ID) : 
        m_ID(a_ID){}

    TrialImpl(const TrialImpl& rhs)
    {
        // make a deep copy (perhaps use default copy constructor)
        m_ID = rhs.m_ID;
        m_Frames = rhs.m_Frames;
    }

    ID m_ID;
    std::vector<Frame> m_Frames;
};

Trial::Trial(ID a_ID) :
    m_Impl(std::make_unique<TrialImpl>(a_ID))
{
}

Trial::Trial(const Trial& rhs) :
    m_Impl(std::make_unique<TrialImpl>(*rhs.m_Impl))
{
}

Trial::Trial(Trial&&) noexcept = default;
Trial::~Trial() = default;

Trial& Trial::operator=(Trial rhs)
{
    swap(rhs);
    return *this;
}

void Trial::swap(Trial& rhs)
{
    // we can just let std::swap swap the unique pointers
    std::swap(m_Impl, rhs.m_Impl);
}

ID Trial::GetID() const
{
    return m_Impl->m_ID;
}
...