how to initialise a vector of vectors with existing vectors ?

Hi all,
I would like to initialise a vector of vectors with existing vectors, like this :

vector<vector<uchar> > vectorOfVector = {mVec1, mEVec2, mVec3};
Here, I am in a method definition of a class where these vectors are declared as attributes :
1
2
3
	std::vector<uchar> mVec1;
	std::vector<uchar> mVec2;
	std::vector<uchar> mVec3;


If I proceed like that, it compiles, executes, but when I deal with
vectorOfVector[0].push_back('a');
for example, mVec1 does not receive 'a' - it remains empty.

If I check the vector address, &mVec1 != &vectorOfVector[0], so the method to initialise vectorOfVector I used is not correct.

If I try with references, like that :
vector<vector<uchar>& > vectorOfVector = {mVec1, mEVec2, mVec3};
The compiler issue an error :
‘const’ qualifiers cannot be applied to ‘std::vector<unsigned char>&’


So, how could I do that please ?
Cuuldn't you make a vector of a structure of 3 chars (or an array of 3 chars), and just keep a reference to that vector?

For the compilation errror, you might be passing mVec1, mVec2 and MVec3 as const arguments to the current function, and since you keep a reference and not a copy, the constness would have to be kept
Last edited on
You could create a class "myVector" then use those 3 vectors as your public variable then create another one as a private to create an overloaded operator that can access and store the data.
Thanks for your reply bartoli.

The answer is no. For the internal vector<uchar>, I don't know a priori their size. They are filled with push_back and may have a few elements or hundreds. So I need the flexibility of vectors, and so the use of vector<vector<uchar> >.

One alternative that should work is vector<vector<uchar>* >, but I would like to avoid it because it is far heavy to manage.

When I try to analyse what happens here :
vector<vector<uchar> > vectorOfVector = {mVec1, mEVec2, mVec3};
I think it uses the default constructor and then pass the values. But it does not delete the objects created to use the existing ones instead. I don't understand why the compiler does not issue an error here.

On the contrary, I don't understand why the reference version :
vector<vector<uchar>& > vectorOfVector = {mVec1, mEVec2, mVec3};
does not work ???
Last edited on
don't understand why the reference version :
vector<vector<uchar>& > vectorOfVector = {mVec1, mEVec2, mVec3};
does not work ???

references are not objects, they cannot be stored in a container (they have no size!)

You could make a vector of reference wrappers:
vector< reference_wrapper<vector<uchar>> > vectorOfVectorRefs = {mVec1, mEVec2, mVec3};
Thanks very much Cubbi. I am going to try it now.....
The compiler disagrees :
Error : could not convert ‘{((LineObject*)this)->LineObject::mVec1, ((LineObject*)this)->LineObject::mVec2, ((LineObject*)this)->LineObject::mVec3}’ to ‘std::vector<std::reference_wrapper<std::vector<unsigned char> > >’
I think the error does not deal with your declaration of a vector of vectors. For example the following code is successfully compiled and executed with GCC 4.7.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>


int main()
{

   {
      std::vector<char> v1 = { 'a', 'b', 'c' };
      std::vector<char> v2 = { '1', '2', '3' };
      std::vector<std::vector<char>> v = { v1, v2 };
      
      v[0].push_back( 'd' );      
      v[1].push_back( '4' );      
      
      for ( const auto &x : v )
      {
         for ( auto c : x ) std::cout << c; 
         std::cout << std::endl;
      }
   }

   return 0;
}      


The result is

abcd
1234
Last edited on
lalebarde wrote:
The compiler disagrees

Works for me: http://ideone.com/imK19 (fixed link)

@vlad: OP wants v[0].push_back('d') to modify v1, based on "mVec1 does not receive 'a' - it remains empty."
Last edited on
@vlad from moscow : waaooo !!!! But I have only gcc 4.5.3 available. So no auto pointers. The good news is, with a little adaptation to compensate for the lack of auto pointers, it works :

1
2
3
4
5
6
7
	std::vector<char> v1 = { 'a', 'b', 'c' };
	std::vector<char> v2 = { '1', '2', '3' };
	std::vector<std::vector<char> > v = { v1, v2 };
	for ( size_t i = 0; i < v.size(); i++ ) {
	    for ( size_t j = 0; j < v[i].size(); j++) cout << v[i][j];
	    std::cout << std::endl;
	}


But in the frame of an object, it does not :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class C64 {
public:
	vector<char> v1;
	vector<char> v2;
	void printV() {
	      vector<vector<char> > v = { v1, v2 };
	      for (char i = 'a'; i < 'd'; i++) v1.push_back(i);
	      for (char i = '1'; i < '4'; i++) v2.push_back(i);
	      for ( size_t i = 0; i < v.size(); i++ ) {
	         for ( size_t j = 0; j < v[i].size(); j++) cout << v[i][j];
	         std::cout << std::endl;
	      }
	}
};

int main() {
    C64 t;
    t.printV();
}


I have only the endl in the output !

@Cubbi : your link looks dead. Thanks for the update. It does not compile for me. What gcc version do you use ? I have added #include <utility> but it is the same.
Last edited on
Vectors copy values that are passed to it. So in the code snip


1
2
3
	      vector<vector<char> > v = { v1, v2 };
	      for (char i = 'a'; i < 'd'; i++) v1.push_back(i);
	      for (char i = '1'; i < '4'; i++) v2.push_back(i);


v1, v2 on the one hand and v on the other hand are two different containers. Your code could work if you would change it the following way

1
2
3
	      vector<vector<char> > v = { v1, v2 };
	      for (char i = 'a'; i < 'd'; i++) v[0].push_back(i);
	      for (char i = '1'; i < '4'; i++) v[1].push_back(i);


Or this way


1
2
3
	      for (char i = 'a'; i < 'd'; i++) v1.push_back(i);
	      for (char i = '1'; i < '4'; i++) v2.push_back(i);
	      vector<vector<char> > v = { v1, v2 };

Last edited on
Vectors copy values that are passed to it.
Too bad ! Thank you very much for the explanations. I will be happy with gcc 4.6 and its move features.

For now, I would like very much to have this reference_wrapper work for me.
@Cubbi : Thanks for the update. It does not compile for me. What gcc version do you use ?


The one used at ideone.com is 4.5.1.

Reference wrappers have been around for a long time, even gcc 4.1.2 (the oldest gcc I can access) has them, in tr1 namespace. But since you're using list-initializer syntax for your vectors in the first post, i assumed your compiler was at least gcc-4.5 or something equally recent.

Maybe try vector< reference_wrapper<vector<uchar>> > vectorOfVectorRefs = {ref(mVec1), ref(mEVec2), ref(mVec3)};
Last edited on
Thanks Cubbi. Now it works, but thought some adaptations :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class C64 {
public:
	vector<char> v1;
	vector<char> v2;
	void printV() {
	      vector< reference_wrapper<vector<char> > > v = {v1, v2};
	      cout << "&v1 = " << &v1 << ", &v2 = " << &v2 << endl;
	      cout << "&v[0].get() = " << &v[0].get() << ", &v[1].get() = " << &v[1].get() << endl;
	      for (char i = 'a'; i < 'd'; i++) v1.push_back(i);
	      for (char i = '1'; i < '4'; i++) v2.push_back(i);
	      for ( size_t i = 0; i < v.size(); i++ ) {
	         for ( size_t j = 0; j < v[i].get().size(); j++) cout << v[i].get()[j];
	         std::cout << std::endl;
	      }
	}
};


This works also : vector< reference_wrapper<vector<char> > > v = {ref(v1), ref(v2)};

$ ./test
&v1 = 0x7fff7d822450, &v2 = 0x7fff7d822468
&v[0].get() = 0x7fff3e870500, &v[1].get() = 0x7fff3e870518
abc
123



Note the additional space between > in vector< reference_wrapper<vector<char> > > but that's a new feature of Cx11 to be able to suppress it.

Note the use for me of the reference_wrapper get method to get the reference. Possibly it is a Cx11 new feature to be able to avoid it ?

Once again, a VERY BIG THANK to both of you !



Last edited on
Great !

I could install gcc-4.7.1 for test. But still, in C64, I cannot write v[i][j] instead of v[i].get()[j]

Compilator says :

error : no match for ‘operator[]’ in ‘v.std::vector<_Tp, _Alloc>::operator[]<std::reference_wrapper<std::vector<char> >, std::allocator<std::reference_wrapper<std::vector<char> > > >(i)[j]’


But probably I can now benefit from move features.....
Topic archived. No new replies allowed.