template<class T>
CStack<T>::CStack(CStack&& rhs) noexcept
: m_pBase(nulllptr)
, m_iCapacity(0)
, m_iSize(0)
{
swap(rhs);
}
template<class T>
CStack<T>& CStack<T>::operator=(CStack const& rhs)
{
CStack<T> copy(rhs);
swap(copy);
return *this;
}
template<class T>
CStack<T>& CStack<T>::operator=(CStack&& rhs) noexcept
{
swap(rhs);
return *this;
}
template<class T>
void CStack<T>::swap(CStack<T>& other) noexcept
{
using std::swap;
swap(m_pBase, other.m_pBase);
swap(m_iCapacity, other.m_iCapacity);
swap(m_iSize, other.m_iSize);
}
Now if we look at the assignment operators. We can optimize them together into a single assignment that works for both move and copy.
template<class T>
CStack<T>::CStack(CStack&& rhs) noexcept
: m_pBase(nulllptr)
, m_iCapacity(0)
, m_iSize(0)
{
swap(rhs);
}
template<class T>
CStack<T>& CStack<T>::operator=(CStack&&CStack rhs) noexcept
{
// Notice the parameter is a value
// If called with a r-value the parameter is move constructed (if it has one).
// If called with a value or reference (or has no move constructor) the parameter is copy constructed
// The original copy assignment had an internal copy but that
// is taken care of by the parameter above.
// Both copy/move assignment are identical for the last part.
swap(rhs);
return *this;
}
template<class T>
void CStack<T>::swap(CStack<T>& other) noexcept
{
using std::swap;
swap(m_pBase, other.m_pBase);
swap(m_iCapacity, other.m_iCapacity);
swap(m_iSize, other.m_iSize);
}