Почему перегрузка оператора-кандидата '=' должна быть помечена как const? - PullRequest
0 голосов
/ 21 января 2019

Я не могу использовать std::set_union, потому что я неправильно перегружаю оператор присваивания.

Я использую std::set моей собственной структуры, NodeChange_t, которая сама содержит другую структуруpoint_t.Вот перегрузки операторов этих парней:

// ---- defs.h
struct point_t
{
    double x;
    double y;

    ...

    void operator=(const point_t &p)
    {
        x = p.x;
        y = p.y;
    }

    ...

};


struct NodeChange_t
{
    SNode node;
    point_t change;
    ListDigraph *graph;

    ...

    void operator=(const NodeChange_t &otherChange)
    {
        this->node = otherChange.node;
        this->change = otherChange.change;
        this->graph = otherChange.graph;
    }

    ...

};

// ---- _2DSurface.cpp

//Problematic code:
void _2DSurface::updateInnerSurfaceV2(_2DSurface &outerSurf, std::set<NodeChange_t> *nodeChanges)
{
    std::set<NodeChange_t> additions;

    ...

    // add stuff to additions
    std::set_union(additions.begin(), additions.end(), nodeChanges->begin(), nodeChanges->end(), nodeChanges->begin());

    ...

}

В этом случае я хочу, чтобы *nodeChanges был перезаписан.Но ошибка, которую я продолжаю получать:

src/_2DSurface.cpp:308:7: note: in instantiation of function template specialization
      'std::__1::set_union<std::__1::__tree_const_iterator<ct, std::__1::__tree_node<ct, void *> *, long>,
      std::__1::__tree_const_iterator<ct, std::__1::__tree_node<ct, void *> *, long>, std::__1::__tree_const_iterator<ct,
      std::__1::__tree_node<ct, void *> *, long> >' requested here
        std::set_union(nodeChanges->begin(), nodeChanges->end(), additions.begin(), additions.end(), nodeChanges.begin());
include/defs.hpp:258:7: note: candidate function not viable: 'this' argument has type 'const std::__1::__tree_const_iterator<ct,
      std::__1::__tree_node<ct, void *> *, long>::value_type' (aka 'const ct'), but method is not marked const
        void operator=(struct ct &otherChange)

Как вообще имеет смысл, что оператор присваивания будет помечен const, если весь смысл состоит в том, чтобы изменить то, что находится слева?Я возился с классификатором const, но, похоже, никуда не денусь.Любая помощь приветствуется.

1 Ответ

0 голосов
/ 21 января 2019

Как вообще имеет смысл, что оператор присваивания будет помечен const, если весь смысл состоит в том, чтобы изменить то, что находится слева?

Оператор присваиванияне отмечено const.На самом деле, сообщение об ошибке говорит так же;это один из триггеров для ошибки.Посмотрите еще раз на соответствующие части сообщения об ошибке, выделив несколько ключевых моментов:

функция-кандидат недопустима: 'this' аргумент имеет тип [snipped] (он же ' const ct'), но метод не отмечен const

Другой триггер для ошибки состоит в том, чтообъект, получивший назначение, помечен const.Если вы посмотрите на типы, упомянутые в сообщении об ошибке, вы можете заметить «const_iterator».Это ваша подсказка!Где-то разыменовывается постоянный итератор, и значение присваивается результату.Все задействованные итераторы являются set итераторами, поэтому давайте взглянем на документацию для set.Тип set iterator является постоянным итератором;Вы не можете писать в него.(Для set типы iterator и const_iterator обычно являются псевдонимами для одного и того же типа. Эта избыточность обеспечивает интерфейс, совместимый с другими контейнерами.)

set_unionАлгоритм требует выходного итератора для пункта назначения.set не имеет выходного итератора.Таким образом, даже если слово «set» появляется в «set_union», set_union не может напрямую выводить set.

Также есть еще одна деталь из документации set_union: "Результирующий диапазонне может перекрываться ни с одним из входных диапазонов. " Вы не можете выполнить то, что хотите (заменить один из входов объединением), за один шаг с set_union.Если это инструмент, который вы хотите использовать, вам нужно вывести объединение во вспомогательный контейнер, а затем обновить nodeChanges в отдельном шаге.Однако, вероятно, было бы проще использовать set::insert (вариант 5):

nodeChanges->insert(additions.begin(), additions.end());
...