2

Sorry for the format, I never really posted to a forum like this, so I have to learn the how to a bit.

My problem is: I'm writing a template class, and I'd like to access my containers via multiple kind of [] operators. I read a bit in this subject, so I've been able to make one overloading, but I need some more:

So in my header file, relevant things about my container:

template <class T>
class version_controlled_vector
{
    int rev;                                         
    bool vector_state_changed;
    std::vector< std::string > revision;     
    std::vector< std::vector<T> > v;                 


    //first one works ok, im satisfied with it:
    std::vector<T>& operator[] (const int idx)
    {
        return v[idx];
    }

    //im not sure how to define the further one(s?):
    T& operator[](const int idx2) const
    {
        return v[idx2];
    }
    //...and ofc some other code
};

//to have these usages at my main.cpp:

version_controlled_vector<int> mi;
version_controlled_vector<std::string> ms;

//this works, and i d like to keep it,
5 == mi[ 0 ][ 0 ];

//and i d like to have these two usages too:
//getting the first character of the stored string:

'H' == ms[ 0 ][ 0 ];    // with the first overload from the header ms[0][0][0]    
works  to get the first character of the string for eg "Hello" 
but, i have to use  the ms[0][0] format to achieve this

//and this:
4 == mi[ 0 ]; // i d like this as if it d behave like 4 == mi[0][0];

I don't really get how can I use the single[] when I made an overload to use the [][]

The only solution I have read about is maybe const-overloading, but I'm not sure at all, I'm quite a weakie.

Thanks for ideas!

4
  • First off, welcome to StackOverflow (Not a forum, but a Q&A site). Now, going to the basics: What do you mean by "version-controlled vector? Does it mean your class must start a new revision whenever the content of the container changes? Because then you are definitely exposing the internal vector too much. (Which btw. already has a subscript operator) Related reading: Operator overloading Commented Jun 29, 2014 at 22:07
  • I don't understand what you are after. You want mi[0] to be an int, but mi[0][0] to also be an int? Commented Jun 29, 2014 at 22:12
  • Your intention for overloading operator[] is not clear at all. And what part does revision play in any of this? If none, why is it even in your sample? Commented Jun 29, 2014 at 22:17
  • Vaughn Cato: yes, i d like to access mi[0][0] with the syntax mi[0], so to an int. WhozCraig: yes revision is not really relevant part here. This program is practising, and its my first post, so i made this mistake, at least leared from it :) Basically its a container, where i can store data of different versions in separate vectors. revision vector can contain a comment for each version. main is made by someone else, and i have to implement the header. to say the truth goal of single [] is a bit unclear for me, especially if we have [][] to access everyting. anyway thanks for answers Commented Jun 29, 2014 at 22:37

2 Answers 2

1

I think you are muddying the interface of the class. The expectations from the class are:

  1. Get the i-th value from the j-th version.
  2. Get the i-th value from the latest version.
  3. Get the j-th version.

You have the option of using the overloaded operator[] function to get those values but, it will be better to have functions that reflect the interface.

// Get the versionIndex-th version.
std::vector<T>& getVersion(int versionIndex);

// Get the itemIndex-th value from the versionIndex-th version.
T& getItem(int versionIndex, int itemIndex);

// Get the itemIndex-th value from the latest version.
T& getItem(int itemIndex);

Then, the implementation would be simpler and less confusing.

std::vector<T>& getVersion(int versionIndex)
{
    // Make sure to add out of bound checks
   return v[versinIndex];
}

T& getItem(int versionIndex, int itemIndex)
{
    // Make sure to add out of bound checks
   return v[versinIndex][itemIndex];
}

T& getItem(int itemIndex);
{
    // Make sure to add out of bound checks
   return v.back()[itemIndex];
}

Given these, the only operator[] that makes sense, at least to me, is one that returns the i-th value from the latest version.

T& operator[](int itemIndex);
{
    // Make sure to add out of bound checks
   return v.back()[itemIndex];
}
Sign up to request clarification or add additional context in comments.

5 Comments

Why not use a magic proxy? It can just work for this case, unless T has a subscript operator...
@Deduplicator, please elaborate what you mean by "magic proxy".
Letting the subscript return a class which can be implicitly converted to T, as well as providing a subscript operator for the second level.
@Deduplicator, I looked for a way to do that, but I didn't find a simple way.
@captain_stack, The outcome of ms[0][0] depends on the what ms[0] evaluates to. If you are happy with ms[0] returning the 0-th item of the latest std::vector<std::string>, then, the function I have in the answer is good.
0

It's a bit tricky one, you need to realise that when you write

version_controlled_vector<int> mi;
5 == mi[0][0];

during the second fetch you're no longer accessing your version_controlled_vector class but the inner property of it and it's type is std::vector<T> which has its own subscript operator that you call in the second [0].

To control the subscript operator of the second fetch you need to create another class that derives from std::vector<T> and has overloaded subscript operator. Then you should use this class instead of the std::vector in the implementation of version_controlled_vector.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.