a-one a-one - 14 days ago 5
C++ Question

overloaded bracket operator for std::list

I was wondering how I would go about creating an overloaded bracket operator that would provide the location of an element in an std::list.

the list declaration in my class is as follows:

std::list<Stimulation*> configuration;


the overloaded bracket operator declaration is:

std::list<Stimulation*>::operator[](const int);


I would figure that the defintion of the bracket operator would go as follows:

std::list<Stimulation*>::operator[](const int position)
{
auto i = configuration.begin();
return i + position;

***OR***

std::list<Stimulation*>::iterator i = configuration.begin();
return i + position;
}


I am new to this concept so any help would be appreciated in the proper way of doing this. I am required to specifically use a list in this situation as I know other containers include the bracket operator as part of the library. Thanks again for your patience and time.

Answer

std::list elements are not contiguous in memory, unlike std::vector elements, that's why no [] operator exists because it would be inefficient, and that's not why lists are made for.

But, as an exercise, you could implement it with a for loop. Here's my naive implementation, lacking const version, and failing with an assertion when out of bounds:

#include <list>
#include <iostream>
#include <cassert>

using namespace std;

class MyList : public list<int>
{
public:

    int &operator[](int pos)
    {
       int count=0;
       for (auto &it : *this)
       {
          if (count==pos) { return it;}
          count++;
       }
     assert(false);
   }
};


int main()
{
    MyList l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    l.push_back(4);
    cout << l[2] << endl;
    return 0;
}

Access time is very bad if element is at the end of the list (O(N)) because you cannot add position to list::begin().

I suppose you could "cache" the last asked offset & iterator so if caller asks for offset+1 (which is frequent in programs) you can just advance without resuming from the start.

Note: just saw the comment about std::advance. Not used there (didn't know it).