2

I have a vector. What I want to do is store a value at the first index of the vector. However, this value is for errors and so I would like to refer to this value like vector_ [-1]. How do I go about with this?

I came up with one solution. What I'm doing is creating a new vector and assigning the new vector to this vector.

vector_.resize(required_size+1);
vector_ = std::vector<T> (vector_.begin()+1,vector_.end());

At this point could I legally use vector_[-1]? If not, please help me with other solutions.

EDIT I found a workaround. Though its not vectors with negative indexing, I'm using a pointer to the second member of the vector so when I do ptr[-1], it points to the first element of the vector.

Rakshith
  • 53
  • 1
  • 6
  • 1
    No, this is wrong. Maybe store it elsewhere? – LogicStuff Jul 14 '16 at 19:08
  • 4
    There's no way to index an unchanged `std::vector` with a negative index. You need to make your own class, perhaps using `std::vector` internally. – Kuba hasn't forgotten Monica Jul 14 '16 at 19:08
  • 4
    The index for the vector is essentially a memory offset. So -1 would be invalid. Seems to me your indexes have special meaning and are more like keys instead. Maybe an std::map would be more appropriate for what you are trying to do. – tdemay Jul 14 '16 at 19:11
  • 1
    @KubaOber That's actually an answer. – πάντα ῥεῖ Jul 14 '16 at 19:12
  • @tdemay, yes -1 would be invalid. But I want `vector_` to point to the second element so that when I say `vector_[-1]` it points to the first element. There is no illegal memory access here – Rakshith Jul 14 '16 at 19:15
  • @Rakshith: you can do that with an array, but not with a vector. – lorro Jul 14 '16 at 19:16
  • @Rakshith : Can you please elaborate what do you mean by vector_ to point to the second element. – kadina Jul 14 '16 at 19:16
  • Why use `-1` for this? It sounds like you want index `0` to have a _special_ meaning so if you're not going to create a new type then use `std::vector` with a convention that uses the `0` index for the error and avoid the confusing `-1` syntax. – James Adkison Jul 14 '16 at 19:20
  • When I say `vector_[0]`, it should actually refer to the second element of the initially allocated vector memory. `vector_[-1]` should give me the actual first element. Just want the indexes to start from -1. Because negative index means an error in my code – Rakshith Jul 14 '16 at 19:21
  • 2
    `vector_[-1]` actually means `vector[std::numeric_limits::max()]`, because `std::vector::size_type` is unsigned. You will never be able to have a negative index in `std::vector` – KABoissonneault Jul 14 '16 at 19:22
  • 2
    You cannot change what vector does internally. It is what _internally_ means. Your best bet is to create your own class which will _internally_ convert indices to those expected by vector. – Revolver_Ocelot Jul 14 '16 at 19:24
  • 1
    Index `0` of a `std::vector` should never refer to the second argument because no one would expect it to work that way. Do what @KubaOber suggested and create a new type which may have any semantics you desire. – James Adkison Jul 14 '16 at 19:24
  • @Rakshith, but it is invalid memory access. It's direct access to memory. That's why it's so fast. It works just like a C-Style array would. You are asking it to go to the beginning of the block of memory for the vector and go backwards sizeof(value_type) – tdemay Jul 14 '16 at 19:25
  • 1
    actually @KABoissonneault is right. I forgot about it being unsigned. You will not be going backwards, you'd be jumping forward MAXINT. – tdemay Jul 14 '16 at 19:29
  • 1
    What is your expectation of the behavior of begin ()? size ()? If you add one of these vectors to another? – kfsone Jul 14 '16 at 19:40
  • What do you mean @kfsone – Rakshith Jul 14 '16 at 19:44
  • 1
    @Rakshith If you have a vector that has a [-1] index, what would you expect `begin()` to return? The -1 element or the 0th element? Would you expect `size()` to include the -1 element or to return `actual_size() - 1`? This affects code like `if (index < v.size()) return v[index]`. For a newly constructed `negative_index_vector`, if I do a `push_back` does it go into position -1 or position 0? Is the vector empty if only the -1 index is populated? If not, then `if (!v.empty()) return v[0]` is broken, but if it is then how do you tell if the -1th element is present/populated? – kfsone Jul 15 '16 at 01:54

3 Answers3

2

You can not have negative indices in , unless of course you provide your own class of a vector that decays that.

For, example check the ref:

Prototype: reference operator[] (size_type n);

Parameters: n Position of an element in the container. Notice that the first element has a position of 0 (not 1). Member type size_type is an unsigned integral type.

Here is a class that could do what you want:

// Example program
#include <iostream>
#include <string>
#include <vector>

class myVector {
public:
  int get(int index) { return v[index + 1]; }
  void push_back(int value) { v.push_back(value); }
  void print() {
      for(unsigned int i = 0; i < v.size(); ++i)
        std::cout << v[i] << " ";
      std::cout << "\n";
  }
  const int& operator[](int index) const { return v[index + 1]; }
private:
  std::vector<int> v;
};

int main() {
  myVector v;
  v.push_back(404); // error code
  v.push_back(32);  // real data
  v.print();
  std::cout << v[-1] << std::endl;
  std::cout << v.get(-1) << std::endl;
  return 0;
}

Output (Live Demo):

404 32 
404
404

Since you are new to C++, operator overloading might puzzle you, skip it for now and come back later and read Operator overloading.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Thanks @gsamaras. Didn't expect such quick replies! – Rakshith Jul 14 '16 at 19:49
  • 1
    @Rakshith Except it doesn't work: it's not a bidirectional random access container that `std::vector` is. Designing container classes isn't exactly a beginner's job, and answers such as this trivialize the matter to the point of uselessness. All the other answers at the moment suffer from this issue :( – Kuba hasn't forgotten Monica Jul 14 '16 at 20:10
  • Will it be useful to inherit `myVector` from `std::vector`? Then all the functionality of `std::vector` could be reused and only the needed parts changed. – ilya1725 Jul 14 '16 at 20:10
  • 1
    @ilya1725 Only as long as you **privately** inherit from `std::vector`, and explicitly expose the functionality you need through `using` in a public section. `myVector` is not a `std::vector` anymore once its indexing is reimplemented. Don't break [LSP](http://stackoverflow.com/q/56860/1329652)! – Kuba hasn't forgotten Monica Jul 14 '16 at 20:11
2

Here's the basic starting point of a vector where you can specify the (signed) lower and upper indexes

#include <vector>
#include <cassert>
#include <iostream>
#include <iomanip>


template<class T>
struct any_index_vector
{
    any_index_vector(int min, int max)
    : _zero_index(min)
    , _storage((max - min))
    {
        // assert min - max
    }

    T& operator[](int index)
    {
        assert(index >= lower_limit());
        assert(index <= upper_limit());
        return _storage[index - _zero_index];
    }

    T& operator[](int index) const
    {
        assert(index >= lower_limit());
        assert(index <= upper_limit());
        return _storage[index - _zero_index];
    }

    int upper_limit() const {
        return _zero_index + int(_storage.size());
    }

    int lower_limit() const {
        return _zero_index;
    }

    int extent() const {
        return upper_limit() - lower_limit();
    }

    int _zero_index = 0;
    std::vector<T> _storage {};
};

int main()
{
    any_index_vector<int> v(-1, 9);
    for (int i = -1 ; i < 10 ; ++i) {
        v[i] = (i+6);
    }

    for (int i = -1 ; i < 10 ; ++i) {
        std::cout << "position: " << std::setw(2) << i << " : " << v[i] << std::endl;
    }
}

expected output:

position: -1 : 5
position:  0 : 6
position:  1 : 7
position:  2 : 8
position:  3 : 9
position:  4 : 10
position:  5 : 11
position:  6 : 12
position:  7 : 13
position:  8 : 14
position:  9 : 15
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
1

I dont understand why you want to do this. You could as well store the extra value in the first element and access it via vector_[0]. However, if you insist on using -1 as index, then I see only one proper way to do this:

template<typename T>
class {
public:  
    T& operator[](int index){
        if (index==-1) { return value; }
        else { return vector[index]; }
    }
private:
    T value;
    std::vector<T> vector;
}

However, I would strongly suggest not to start something like this. You will waste lots of code just to get something that acts similar to a vector while you could simply use a plain std::vector and forget about the -1 indexing.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185