0

I have a structure with some properties and a set. I have multiple instances of those structs inside another set. When I try to add something to the set inside the struct:

test2.cpp: In function ‘int main()’:
test2.cpp:42:22: error: no matching function for call to ‘std::set<int>::insert(int) const’
 (it->ys).insert(2);

I admit it may have something to do with the initialization of the sets. I have a C background and don't fully grasp how object initialization and declaration work in C++. The code:

#include <stdlib.h>
#include <set>
#include <utility>

using namespace std;

struct MyStruct {
  long int x;
  set<int> ys;
  friend bool operator<(MyStruct a, MyStruct b) {
    return a.x < b.x;
  }
};

set<MyStruct> ms;

MyStruct *new_ms(long int x) {
  MyStruct *n= (MyStruct*) malloc(sizeof(MyStruct));
  n->x = x;
  n->ys = set<int>();

  return n;
}

int main() {

  pair<set<MyStruct>::iterator,bool> ret;
  set<MyStruct>::iterator it;

  MyStruct *ms1 = new_ms((long int)5);

  ret = ms.insert(*ms1);
  if(ret.second == false) {
    free(ms1);
  }

  it = ret.first;
  (it->ys).insert(2);

}
Joaquim Ferrer
  • 603
  • 6
  • 23
  • Elements of a `std::set` can't be modified. In your set of sets, adding elements to the sub-set would modify it. – François Andrieux Jul 11 '17 at 16:01
  • for sure you should not be mixing STL containers and malloc – pm100 Jul 11 '17 at 16:02
  • Don't use malloc and free in C++ code - malloc will not call constructors, and free will not call destructors. And if you don't understand how initialisation works in C++ (which is _extremely_ important), read a good C++ textbook. –  Jul 11 '17 at 16:02
  • Thanks for the help @NeilButterworth . I always thought it would be something as Java so I didn't give much though. Will do – Joaquim Ferrer Jul 11 '17 at 16:07
  • @FrançoisAndrieux I hope not. The only important part to be constant of the set is the comparator. If that is constant then it should be no problem. (Allthough I admit it's not constant in my struct). Is there a workaround? – Joaquim Ferrer Jul 11 '17 at 16:10
  • The question is repeated yes. Just found that mutable allows me to do what I want. Will close. Thanks! – Joaquim Ferrer Jul 11 '17 at 16:12
  • By the way is the style good? Those pairs, iterators and overloads crack my head. Sorry for abusing you guys/girls... – Joaquim Ferrer Jul 11 '17 at 16:15
  • 1
    @JoaquimFerrer I'm assuming you mean that you made `ys` mutable. Mutable is a terrible hack for this situation. `mutable` is meant to distinguish between bitwise constness and logical constness. In this case, `ys` is almost definitively part of the logical state of the object and should not be `mutable`. Elements in an `std::set` must maintain a sorted order. Modifying elements that are in a set could cause it to be out of order. You are simply using the wrong container for the job. – François Andrieux Jul 11 '17 at 16:15
  • @FrançoisAndrieux but what if I kwon for sure that the mutable elements will NEVER affect the ordering of the set? I though and searched a lot for the right container and the set of sets was the only std that did everything I wanted... – Joaquim Ferrer Jul 11 '17 at 16:20
  • @JoaquimFerrer `mutable` may only be used on members that do not affect the visible state of the object. `ys` is a public member, so it's as visible as can possibly be. If you would share your requirements and what part of `std::set` is useful for you, I'm sure we can recommend a more appropriate container. `std::set` is not meant to be used to store mutable objects. Perhaps you could use a `std::set` of pointers, but it's hard to see the advantage of using `std::set` in that case. – François Andrieux Jul 11 '17 at 16:23
  • @FrançoisAndrieux I've always thought that the interface to `std::set` was unnecessarily restrictive. It's often the case that there will be a particular piece of an object that can be considered a sort key, and the remainder should be able to be modified. It's really a pity that `std::set` can't handle this case. – Mark Ransom Jul 11 '17 at 16:30
  • @FrançoisAndrieux What I'm trying to do is to organize points in 2 dimensions when adding them one by one. It should be possible to get ranges of values from the first dimension, or by fixing the first dimension and geting ranges of values in the second dimension. All in O(log n). I can't create my own data structure because of time requirements (Can' test and debug everything right now). – Joaquim Ferrer Jul 11 '17 at 16:35
  • @JoaquimFerrer You could consider using `std::map>` or a sorted `std::vector` with [`std::binary_search`](http://en.cppreference.com/w/cpp/algorithm/binary_search). – François Andrieux Jul 11 '17 at 16:41

0 Answers0