0

I've got an assignment operator in my class

template<typename T>
T&   array<T>::operator[](int value);

this method can be used like a const and none const method:

array[100] = value; // None const cause if size > array.size(): resize it!

std::cout << array[0]; // const

If my object is instanced as a const object and ask me to resize it I must throw an exception.

How can I know that I am instanced as a const object ?

nsvir
  • 8,781
  • 10
  • 32
  • 47

4 Answers4

2

Just add a second version of your [] operator with a const modifier, it'll be called for const objects.

This one for non const objects:

template<typename T>
T& array<T>::operator[](int value);

And this one will be called for const objects:

template<typename T>
T& array<T>::operator[](int value) const;

That said don't forget that const in C++ is pretty weak and a simple const_cast will bypass it so you may think about another protection too.

Edit: note (see comments) that according to what you're doing you may declare return type of const function as const T&. It may be your case or not (if collection is const then its elements have to be const too?).

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • 2
    The return type of the `const` overload should be `const T&`. – juanchopanza Jan 22 '14 at 15:25
  • @juanchopanza well, it may be but it depends on what OP is doing. A collection may be const but its elements non-const. – Adriano Repetti Jan 22 '14 at 15:28
  • That would be a rather strange use of `const`, especially for a container which otherwise likes to pretend it owns the elements. –  Jan 22 '14 at 15:41
  • @delnan not really for how he's using that. Imagine array, I'd feel "strange" to have a "const int" moreover I may feel natural to get Person from const array (note Person is non const). I think he needs that primary because he performs an array resize when assigning/reading from an out of range index. – Adriano Repetti Jan 22 '14 at 15:50
  • @Adriano If you return a non-const reference, you allow things like `arr[i] = something;` and `arr[i].mutate_me();` and `arr[i]++;`. While it's technically possible to do this safely, it makes `const array` much less useful (how often do you want to prevent resizing, but not changing elements?). The closest analogue to the behavior OP describes is `std::map`'s indexing, and of that there simply is [no `const` overload for `operator[]`](http://stackoverflow.com/q/13902742/395760). –  Jan 22 '14 at 15:52
  • @delnan I'm not discussing about that (some people think A, someone else B, in general I would agree with you). Frankly an auto-sizing array is pretty confusing _per se_ but if you're using that I guess most of times you want to "freeze" it but you want still mutate its items (or you'll declare them as const too). – Adriano Repetti Jan 22 '14 at 16:08
  • @Adriano AFAIK declaring the items const makes it impossible to use the vector in any way. You can't selectively cast between `array` and `array` since templates are invariant, and you usually can't even instanciate `array` because `array<>` necessarily contains some lines assigning or otherwise modifying items. –  Jan 22 '14 at 16:11
  • @delnan sorry I didn't understand what you mean with last sentence in your commnet (...can't even...modifying items). – Adriano Repetti Jan 22 '14 at 16:13
  • 1
    @Adriano Try `std::vector` for example. It doesn't work. Neither do most other containers. –  Jan 22 '14 at 16:21
  • @delnan ah OK, tnx I got what you mean. – Adriano Repetti Jan 22 '14 at 16:23
2

Just provide a const version:

template<typename T>
const T&   array<T>::operator[](int value)const
{
  // throw exception
}

The const version will be called when your instance is constant, the non-const will be called when it's not constant.

Sean
  • 60,939
  • 11
  • 97
  • 136
0

this method can be used like a const and none const method:

You're wrong here. To use [] as a const method you should overload it with const definition of the method (const {/*definition*/}).

Additionally you should make your int argument (or unsigned the best) also a const variable.

That means declaring following headers:

template<typename T>
T&   array<T>::operator[](const int value);       // Read-write
template<typename T>
T&   array<T>::operator[](const int value) const; // Read
Konrad Talik
  • 912
  • 8
  • 22
-1

I understand that you don't want just to have const and non-const version of your operator, but what you want is to know if the value returned by the operator is modified or not, and if it is used in a context where it is not modified, exception should be thrown for out-of-range index. If so, I do not think it is possible in C++.

Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
  • I wonder why the downvote? From the OP's code it is clear that different two versions of operator for the same non-const object (named 'array') are required. – Wojtek Surowka Jan 22 '14 at 15:32