Super Super::transpose() const;
Это похоже на функцию, которая не должна изменять *this
при вызове, но должна возвращать транспонированную версию *this
.
Пример:
#include <algorithm>
Super Super::transpose() const {
Super newMatrix = *this;
std::reverse(newMatrix.elements.begin(), newMatrix.elements.end());
return newMatrix;
}
Если вы хотите транспонировать *this
на месте, измените его на:
Super& Super::transpose();
Super& Super::transpose() {
std::reverse(elements.begin(), elements.end());
return *this;
}
Если вы должны сначала создать временный объект, вы можете, но вы не можете присвоить разыменованную Interface*
другой разыменованной Interface*
. Перемещение unique_ptr
работает, хотя:
Super& Super::transpose() {
Super newMatrix = *this;
size_t s = elements.size();
for(size_t i = 0; i < s; ++i) {
elements[i] = std::move(newMatrix.elements[s - i - 1]);
}
return *this;
}
Демонстрация
Вы также можете инкапсулировать std::unique_ptr<Interface>
в класс-оболочку, чтобы добавить конструктор копирования и оператор присваивания (который не поддерживается std::unique_ptr
). Делая это, вы можете значительно упростить ваши другие классы. Вашему классу Super
не нужно ничего знать о клонировании. Копирование / перемещение элементов будет работать "из коробки".
Пример оболочки:
class Cell {
public:
Cell() noexcept = default; // empty Cell ctor
explicit Cell(std::unique_ptr<Interface>&& d) noexcept; // converting ctor
// rule of five
Cell(const Cell& rhs); // must be implemented
Cell(Cell&& rhs) noexcept = default; // handled by unique_ptr
Cell& operator=(const Cell& rhs); // must be implemented
Cell& operator=(Cell&& rhs) noexcept = default; // handled by unique_ptr
~Cell() = default; // handled by unique_ptr
explicit operator bool() const noexcept; // proxy for unique_ptr operator bool
void reset() noexcept; // empty the Cell
// dereferencing
Interface& operator*();
const Interface& operator*() const;
Interface* operator->();
const Interface* operator->() const;
std::ostream& print(std::ostream& os) const; // calls: os << data->toString()
// A helper factory to make a Cell of a certain type using the converting ctor
template<typename T, class... Args>
static Cell make(Args&&... args) {
return Cell(std::make_unique<T>(std::forward<Args>(args)...));
}
private:
std::unique_ptr<Interface> data{};
};
std::ostream& operator<<(std::ostream& os, const Cell& c); // calls c.print(os)
Конструктор копирования и оператор назначения копирования могут быть реализованы следующим образом:
Cell::Cell(const Cell& rhs) : data(rhs ? rhs.data->clone() : nullptr) {}
Cell& Cell::operator=(const Cell& rhs) {
if(this != &rhs) data = rhs ? rhs.data->clone() : nullptr;
return *this;
}
Вот демоверсия с 2D-матрицей с использованием std::vector<std::vector<Cell>>
. Такие двухмерные векторы не очень эффективны, но они служат цели демонстрации.