Как перегрузить унарную арифметику с помощью семантики хода - PullRequest
1 голос
/ 24 апреля 2019

Я хотел бы реализовать унарный арифметический оператор с семантикой перемещения для std :: vector.Цель состоит в том, чтобы избежать внутреннего выделения внутри оператора, если оно применяется к значению.

Проблема: следующая операция не компилируется: c = - (a + b)

Причина, по которой это не компилируется, заключается в том, что двоичный арифметический оператор + I реализован для std :: vectorвозвращает const lvalue (так что компилятор будет жаловаться на (a + b) = c, что не имеет смысла).

Бинарный оператор +

template<class T, class AllocVect1, class AllocVect2>
inline const std::vector<T> operator+ (
    const std::vector<T, AllocVect1> &v1,
    const std::vector<T, AllocVect2> &v2) {
    std::vector<T> vout;

    *Compute vout = v1 + v2*

    return vout;
}

Унарный оператор

template<class T, class Alloc>
inline const std::vector<T>& operator- (std::vector<T, Alloc> &&v) {
    std::transform (
        v.begin (), 
        v.end (), 
        v.begin (), 
        [](const auto &val){return -val;});
    return v;
}

1 Ответ

0 голосов
/ 24 апреля 2019

Передайте и верните ваш вектор по значению.

То, что может показаться неинтуитивным, имеет смысл, если учесть следующие вещи:

  1. Временный объект может быть неявно перемещен в параметр значения - копирование не происходит. Это как если бы вы вызывали std::move для локальной переменной.

  2. Этот объект (параметр) можно изменить на месте, так как он не имеет квалификатора const.

  3. Модифицированный объект может быть возвращен, и семантика перемещения снова применяется неявно. Вы никогда не должны возвращать ссылки на локальные переменные - ни ссылки на lvalue, ни на rvalue.

template<class T>
std::vector<T> operator-(std::vector<T> v) { // 1.
    std::for_each( // 2.
        v.begin(), 
        v.end(), 
        [](T& val) {val = -val;});

    return v; // 3.
}

Этот оператор может вызываться как с r-значениями (перемещение + изменение + перемещение), так и с l-значениями (копирование + изменение + перемещение).

При этом, - это преимуществ отдельных перегрузок для const Param& и Param&&, подробности которых уже объяснены в отдельных ответах:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...