Class storing pointers to vector in C++ - c++

I'm implementing a class Aviary, which can store pointers to Bird-objects. Now, I have the following:
class Aviary {
public:
const Bird &operator[](const size_t index) const {
return birds[index];
}
Bird &operator[](const size_t index) {
return birds[index];
}
private:
std::vector<Bird*> birds;
The Bird-objects are stored as pointers in order to avoid object-slicing. However, there is a problem with the operator[]-implementation (Reference to type 'const Bird' could not bind to an lvalue of 'const value_type' (aka 'Bird *const')).
How do I implement the operator[] properly?

Since you store pointers, you should dereference the pointer for return reference.
const Bird &operator[](const size_t index) const {
return *birds[index];
}
Bird &operator[](const size_t index) {
return *birds[index];
}
Side note: use smart pointers, instead of raw pointers.

Two side notes:
The const in a parameter passed by value (const size_t index) is useless and your compiler will ignore it. You can try declaring it with const and removing the const in the implementation: the compiler will correctly consider that your implementation matches the declaration.
The canonical way to implement the non-const version of operator[] is as follows:
As follows
Bird &operator[](size_t index) {
return const_cast<Bird&>(const_cast<const Aviary*>(this)->operator[](index));
}
I know all those const_cast look ugly, but they are both safe and this is the right way to ensure that both versions of operator[] do the same (you just need to maintain the const version from now on), while also making sure that your are not doing any non-const operation in the const version.
Apart from that, the problem with your code is that you are returning pointers, not (references to) the values pointed by them, as Luchian and ForEveR have already pointed out.

You need to dereference:
return *(birds[index]);
birds[index] is a Bird*, so you can't directly return it as a Bird&.

Related

Static pointer to member array for safe operator[] access

I was looking at the source code of boost::gil and I came across this comment and corresponding code in the 2D point class.
const T& operator[](std::size_t i) const { return this->*mem_array[i]; }
T& operator[](std::size_t i) { return this->*mem_array[i]; }
...
private:
// this static array of pointers to member variables makes operator[]
// safe and doesn't seem to exhibit any performance penalty
static T point2<T>::* const mem_array[num_dimensions];
http://www.boost.org/doc/libs/develop/boost/gil/utilities.hpp
Questions:
What does this do exactly?
How does this make operator[] safe?
The definition of the array is relevant – it is
template <typename T>
T point2<T>::* const point2<T>::mem_array[point2<T>::num_dimensions]
= { &point2<T>::x, &point2<T>::y };
The indirection through a pointer-to-member makes it possible to access the x coordinate of a point p as either p.x or p[0], and similarly for p.y and p[1].
This is otherwise sometimes accomplished through (probably undefined) pointer trickery or a (possibly less efficient) branch on the index.
It is of course not absolutely safe since there is no bounds-checking, but it's safe in the sense of being standards-compliant and well-defined.

Can I get a const slice_array from a const valarray?

I have a function that accepts a const reference to a valarray, and I want to be able to slice the array and pass the slice into another function that expects a const slice_array. I know that I can just use operator[] and a slice to get a new, copied valarray out of the original valarray, but I want to avoid the copy. Everything is const, so I feel like that should be okay. However, the documentation for the subscript operator for valarray ONLY returns a slice_array objects when applied to non-const valarrays. This feels kind of a major deficiency in the valarray class. Am I missing something? How do I get a slice of a const valarray without incurring a copy?
Here is an example of what I'm talking about:
void foo( const valarray<double> &big_stuff )
{
const slice_array<double> small_stuff = big_stuff[slice(start, size, stride)];
bar( small_stuff );
}
Thanks!
How do I get a slice of a const valarray without incurring a copy?
There is no way to do this, because of std::valarray not contain std::slice_array
for any request, so it cat not give you just link(pointer,reference) to std::slice_array that you request.
But std::slice_array can contains only three machine words,
hard to imagine situation where not copy of std::slice_array can optimize something. For example from gcc/libstdc++ (only data, functions stripped):
template<typename _Tp>
class slice_array {
const size_t _M_sz;
const size_t _M_stride;
const _Array<_Tp> _M_array;
};
where _Array:
template<typename _Tp>
struct _Array { _Tp* const __restrict__ _M_data; };

why sometime a function return a const, or const reference

First, why return const?
say I have
friend const MyVec operator-(const MyVec& left, const MyVec& right)
so is returning const makes me cannot do:
mva - mvb = mvc;
Second, why return const reference?
if there is:
friend const MyVec& operator++(MyVec& v)
with const I cannot: (++mva) = mvc
if it is
MyVec& operator++(MyVec& v)
I can:++(++mva) // with increment twice.
am I understanding right?
There is not any good reason to return a const object. However, there are many good reasons to return pointers or references to const objects.
The program might have an object that is very expensive to copy, so it returns a reference. However, the object should not be changed through that reference. For example, it might be part of a sorted data structure and if its values were modified it would no longer be sorted correctly. So the const keeps it from being modified accidentally.
Arithmetic operator functions should not return const objects, because of exactly the problems in your question.
Dereferencing an iterator should return a const reference. That is if it is operating on a collection of const objects or possibly on a const collection. This is why class functions sometimes have two copies of a function with the second copy using a const on the function itself, like this:
T& operator[](size_t index);
const T& operator[](size_t index) const;
The first function would be used on non-const objects and the second function would be used for const objects.
Yes your understanding is correct. To avoid accidental assignments, one can return an object by const or const reference.
With operator -, you return an object by value. To avoid it getting edited accidently, one can return by const value, because anyways the object will be mostly a temporary.
For operator ++, conventionally it returns reference, however to avoid situations as (++ x) = y; you can return it by const reference.

Overloading subscript operator []

Why does it require to be a member function of a class for its operation and is good to return a reference to private member?
class X
{
public:
int& operator[] (const size_t);
const int &operator[] (const size_t) const;
private:
static std::vector<int> data;
};
int v[] = {0, 1, 2, 3, 4, 5};
std::vector<int> X::data(v, v+6);
int& X::operator[] (const size_t index)
{
return data[index];
}
const int& X::operator[] (const size_t index) const
{
return data[index];
}
As to why is it required to have [] as a member, you can read this question (by yours sincerely). Seems it's just the way it is with no really really convincing explanation.
As to why return reference?
Because you want to provide a way not only to read, but also (for non-const objects) to modify the data. If the return weren't a reference (or some proxyr)
v[i] = 4;
wouldn't work.
HTH
It needs to be a member function according to 13.5.5:
operator[] shall be a non-static
member function with exactly one
parameter. It implements the
subscripting syntax
A reference to a private member is completely OK and pretty common. You hide the details from the user of your class, but still provide the functionality you need (ability to modify individual elements)
Your data variable likely shoudn't be static though, unless you really want to share it among all instances of your class
For the first question, it is just the way they decided it had to be, i.e. you can't do:
T operator[]( const X &, size_t );
as an external function.
And yes, you are fine returning a reference to a private member, non-const if you allow your users to write there, non-const otherwise.
In your example though data is static, which does not make sense if that is the source for what it returns.
What would the syntax be for calling a non-member operator[]? Any syntax for that would be awkward. operator[] takes ones parameter within the [ and ] and that is usually an index or some kind of data necessary to find an object.
Also, yes, it is a good idea to return a reference, even if it's a private member. That is exactly what STL vectors do and just about any other class I can think of that I've ever used that provides operator[]. It would be advised that it the usage is maintained.

C++: "const" in front of a class method

Taking for example this method declaration:
const Vector Vector::operator - ( const Vector& other ) const;
I know that the second const makes the Vector passed as an argument immutable, and that the last const declares that the method does not change the current instance of the Vector class....
But what exactly does the first const mean or lead to?
It is an outdated security measure to prevent nonsense code like a - b = c to compile.
(I say "outdated" because it prevents move semantics which only works with non-const rvalues.)
The first const means that this operator will return a constant Vector object.
It means the return value is a const Vector.
It has more meaning in cases such as this: const int& Vector::get(int index) const;