2

I am stuck with using immutable objects with collections. Let assume I have the following class :

 //in .h
 class Data {
 public:
      Data(const DataObj& data);
      Data(const Data&);
      const DataObj& getDataObj() const;
 private:
      const DataObj _data; //actually several objects or simple type
 }

 inline const DataObj& Data::getDataObj() const {return _data};

 //in .c
 Data(const DataObj& data)  : _data(data){}; 
 Data(const Data& original) : _data(original._data){}

The issue is that when I want to use collections, I have the error

   in member function Data&Data::operator(const Data&);
   instantiation from 'typename QMap<Key,T>::iterator QMap<Key, T>::insert(const Key&, const T&)[with Key = int, T = Data]'
   instantiation from here
   error : non-static const member 'const DataObj Data::_data', can't use default assignment operator

Now defining an assignment operator doesn't seems to make sense, since its prototype will be

 Data& operator=(const Data&);

What should I do? Am I forced to remove all constant qualifiers in order to use my class inside collections? Or use pointers?

UmNyobe
  • 22,539
  • 9
  • 61
  • 90

3 Answers3

2

If you are instantiating your map like this

QMap <MyKey, Data> 

I guess you should always define an assignment operator for Data (default or your own).

You should try using pointers, as you suggest, like this

QMap <Mykey, Data*> 
QMap <Mykey, QSharedPointer<Data>> 

If you take a look to the QMap code http://code.woboq.org/kde/include/QtCore/qmap.h.html, some operators/members return < T >, so it would need assignment defined.

kikeenrique
  • 2,589
  • 2
  • 25
  • 46
1

You can make the data member non-const, but provide only const access to users of the class, except for the assignment operator:

class Data {
 public:
      Data(const DataObj& data);
      Data(const Data&);
      Data& operator=(const Data&);
      const DataObj& getDataObj() const;
 private:
      DataObj _data;
 };

In this way, assignment is the only operation that can mutate an existing object. You would then have to make sure you provide access to const instances of this type in any public interfaces.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 2
    As much as I agree with this, it's a somewhat pragmatical approach. I think you should mention that it must be complemented by taking care that containers are also only exposed as `const`. (From whatever class/abstraction is using them.) – Luc Danton Sep 19 '12 at 13:12
  • 1
    @LucDanton agreed, although the only mutating operation would be assignment. I have tried to provide some explanations along those lines. – juanchopanza Sep 19 '12 at 13:29
  • 1
    I didn't explicitly provided an assignment operator... about removing the const, I thought about it. I also though of a nasty bug I had when coding with a friend. [Like this one](http://stackoverflow.com/a/214718/1122645) – UmNyobe Sep 19 '12 at 13:58
  • 1
    @UmNyobe I cannot see how you can get those kind of errors when the only non-const operation you can carry out is assignment. – juanchopanza Sep 19 '12 at 16:20
1

Use good stl containers instead of bad Qt:

This will fail to work with Qt container due to COW, but it ok (until you try to copy the container) with stl

class C
{
    C operator=(const C&);
};

int main()
{
    std::map<int, C> cc;
    cc.insert(std::make_pair(0, C()));
}
Lol4t0
  • 12,444
  • 4
  • 29
  • 65