std::is_move_assignable_v false, хотя есть оператор присваивания перемещения

Контекст: у меня есть класс DLXMatrix с некоторым атрибутом, который является вектором некоторого локального класса с именем Header. Каждый Header содержит некоторый указатель на некоторые другие Header, которые ссылаются на элементы того же вектора (подумайте о структуре, которая является и вектором, и двусвязным списком). Как следствие, я не могу использовать конструктор копирования по умолчанию и операторы присваивания, поскольку они будут указывать на исходные элементы, а не на копию. Примечание. Я слежу за тем, чтобы размер вектора никогда не изменялся и не перемещался в памяти.

#include <type_traits>
#include <vector>

class DLXMatrix {
  private:
    struct Header {
        Header *left, *right;
    };
    std::vector<Header> heads;
  public:
    DLXMatrix() = delete;
    explicit DLXMatrix(size_t nb_col);
    DLXMatrix(const DLXMatrix &);
    DLXMatrix &operator=(DLXMatrix other);
    DLXMatrix(DLXMatrix &&) = default;
    DLXMatrix &operator=(DLXMatrix &&other) = default;
    ~DLXMatrix() = default;
};

static_assert(std::is_move_constructible<DLXMatrix>::value);
static_assert(std::is_move_assignable<DLXMatrix>::value);

Если я не ошибаюсь, хотя я определил собственный оператор копирования и присваивания, деструктор по умолчанию, конструктор перемещения и копия присваивания перемещения должны работать, как и ожидалось, без утечек. Теперь я хотел бы использовать std::swap, но он отказывается компилироваться, потому что мой класс не может быть назначен перемещением:

dlx_matrix.cpp:257:5: error: static_assert failed due to requirement
      'std::is_move_assignable_v<DLX_backtrack::DLXMatrix>'
    static_assert(std::is_move_assignable_v<DLXMatrix>);

Итак, мои вопросы:

  • это разумный способ делать вещи?
  • почему DLXMatrix нельзя назначать для перемещения?

Если это имеет значение, я компилирую с g++ 7.5.0 и clang++ 6.0.0 со стандартным c++17.


person hivert    schedule 30.10.2020    source источник
comment
Есть ли причина, по которой оператор присваивания копии не принимает const DLXMatrix &? Изменение решает проблему (у меня нет хорошего объяснения, почему).   -  person IlCapitano    schedule 30.10.2020
comment
Я заметил то же самое. Похоже, что-то в этом мешает. Что действительно странно, учитывая, что копирование и обмен — известная идиома.   -  person NathanOliver    schedule 30.10.2020
comment
См., например. почему это все портит: stackoverflow.com/questions/17961719/. Я не знаю, как реализован is_move_assignable, но, вероятно, он даже не видит вашего фактического оператора присваивания перемещения.   -  person AVH    schedule 30.10.2020
comment
@IlCapitano: мне нужна была копия, поэтому я понял, что вызов конструктора копирования во время вызова функции экономит одну строку. Код работает сейчас. Спасибо за улов! Я с радостью приму его, если вы напишете правильный ответ!   -  person hivert    schedule 30.10.2020
comment
Похоже, что деформированный конструктор копирования скрывает конструктор перемещения. Результаты могут отличаться от компилятора к компилятору.   -  person Michaël Roy    schedule 31.10.2020


Ответы (1)


Я отправляю ответ после указания @IlCapitano.

В реализации operator= мне нужно было сделать копию и я решил сделать это благодаря вызову по значению. Итак, прототип был

DLXMatrix &operator=(DLXMatrix other);

вместо стандартного

DLXMatrix &operator=(const DLXMatrix &other);

Эта форма вызова по значению не распознается компилятором/библиотекой как правильный оператор присваивания копии.

person hivert    schedule 12.11.2020