I can't use std::set_union
because I'm not overloading the assignment operator correctly.
I'm using a std::set
of my own struct, NodeChange_t
, which itself contains another struct, point_t
. Here are these guys' operator overloads:
// ---- 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());
...
}
In this case, I want *nodeChanges
to be overwritten. But the error I keep getting is:
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)
How does it even make sense that an assignment operator would be marked const
, if the whole point is to modify what's on the left hand side? I've been messing around with the const
qualifier but can't seem to get anywhere. Any help is appreciated.
How does it even make sense that an assignment operator would be marked
const
, if the whole point is to modify what's on the left hand side?
The assignment operator is not marked const
. In fact, the error message says as much; it is one of the triggers for the error. Take another look at the relevant parts of the error message with some key emphasis:
candidate function not viable: 'this' argument has type [snipped] (aka 'const ct'), but method is not marked const
The other trigger for the error is that the object receiving the assignment is marked const
. If you look around the types mentioned in the error message, you might notice "const_iterator
". This is your clue! Somewhere a constant iterator is being de-referenced and a value assigned to the result. All iterators involved are set
iterators, so let's take a look at documentation for set
. A set
's iterator
type is a constant iterator; you cannot write to it. (For a set
, the iterator
and const_iterator
types are usually aliases for the same type. This redundancy allows an interface that is consistent with other containers.)
The set_union
algorithm requires an output iterator for the destination. A set
does not have an output iterator. So even though the word "set" appears in "set_union", set_union
cannot directly output a set
.
Also concerning is another detail from the set_union
documentation: "The resulting range cannot overlap with either of the input ranges." You cannot accomplish what you want (replace one of the inputs with the union) in one step with set_union
. If that is the tool you want to use, you'll need to output the union to an auxiliary container, then update nodeChanges
in a separate step. Hoewever, it would probably be simpler to use set::insert
(variation 5):
nodeChanges->insert(additions.begin(), additions.end());