Discussion:
vector of vectors
(too old to reply)
Frank
2014-02-11 15:10:10 UTC
Permalink
Dear people,

could someone please help me here? I made a two-dimensional
array, i. e. a vector of vectors, templated:


----- SNIP -----

template< typename VEC2_ELEMENT // element type
class vec2 : public std::vector <std::vector<VEC2_ELEMENT> >
{
public:
// something here

// longest returns the # of elements of the sub-vector with the most elements
int longest()
{
if (size() > 0)
{
// longestindex returns the index of the sub-vector with the most elements
return this->at(longestindex()).size(); // works
// return this[longestindex()].size(); // doesn't work
}
else
return -1;
}
} ;

----- SNIP -----

Now why is it that the "at" statement works but the "[]²
statement returns the # of lines, i. e. the # of sub-vectors?
Example: The whole vec2 contains 3 sub-vectors with
5, 8, and 2 elements. The "works" version returns 8,
the "doesn't work" version returns 3.
Stuart
2014-02-11 17:04:00 UTC
Permalink
Post by Frank
Dear people,
could someone please help me here? I made a two-dimensional
----- SNIP -----
template< typename VEC2_ELEMENT // element type
class vec2 : public std::vector <std::vector<VEC2_ELEMENT> >
{
// something here
// longest returns the # of elements of the sub-vector with the most elements
int longest()
{
if (size() > 0)
{
// longestindex returns the index of the sub-vector with the most elements
return this->at(longestindex()).size(); // works
// return this[longestindex()].size(); // doesn't work
}
else
return -1;
}
} ;
----- SNIP -----
Now why is it that the "at" statement works but the "[]²
statement returns the # of lines, i. e. the # of sub-vectors?
Example: The whole vec2 contains 3 sub-vectors with
5, 8, and 2 elements. The "works" version returns 8,
the "doesn't work" version returns 3.
The expression "this[longestindex()].size()" is translated to
"(this + longestindex())->size()" which means that you treat the
this-pointer as if it pointed to an array of vec2 objects (which it
doesn't), pick the 2nd, 3rd, whatever element of this imaginary array
(IOW, some memory that lies further up the stack) and invoke the method
size on this memory. By sheer luck you didn't get an access violation
(you will, if longestindex returns a larger number), but the returned
value is, of course, complete nonsense.

What you have to do is dereferening the this-pointer, so that you deal
with the actual vec2 object and not the pointer to the vec2 object. Like
this:
return (*this)[longestindex()].size();

Note that *this[longestindex()].size() won't compile because operator[]
has higher precendence than operator*, so *this[longestindex()].size()
is treated as *(this[longestindex()]).size().

Regards,
Stuart

PS: Almost all C++ programmers will tell you that deriving from
std::vector is A Bad Idea(TM) (I think it is Victor Bazarov's
trademark). I can't give you the reasons for this in a nutshell, but it
should be easy to look that up on the internet.

PPS: It would have been even nicer if you had posted a _complete_,
compilable example. Although I was pretty sure that the problem was the
missing dereference of this, I added some code to make a minimal working
example and debugged through this. Not everybody is willing to do that,
especially if it consumes ones spare time.
Frank
2014-02-12 07:49:04 UTC
Permalink
Stuart wrote:

[...]
Post by Stuart
What you have to do is dereferening the this-pointer, so that you deal
with the actual vec2 object and not the pointer to the vec2 object. Like
return (*this)[longestindex()].size();
Stupid me, of course you're right, and it works.

[...]
Post by Stuart
PS: Almost all C++ programmers will tell you that deriving from
std::vector is A Bad Idea(TM) (I think it is Victor Bazarov's
trademark). I can't give you the reasons for this in a nutshell, but it
should be easy to look that up on the internet.
Thanks, I'll look it up.
Post by Stuart
PPS: It would have been even nicer if you had posted a _complete_,
compilable example. Although I was pretty sure that the problem was the
missing dereference of this, I added some code to make a minimal working
example and debugged through this. Not everybody is willing to do that,
especially if it consumes ones spare time.
There could be a misconception on my side: I deliberately
stripped off everything I thought irrelevant, and just for
the purpose to save the time of anyone willing to help.
I've often seen things like that in programming examples,
so I did the same.
Stuart
2014-02-12 21:10:19 UTC
Permalink
Post by Frank
There could be a misconception on my side: I deliberately
stripped off everything I thought irrelevant, and just for
the purpose to save the time of anyone willing to help.
I've often seen things like that in programming examples,
so I did the same.
I had to fill in some stuff and ended up with the following example:

#include <vector>
#include <algorithm>

template< typename VEC2_ELEMENT // element type
class vec2 : public std::vector <std::vector<VEC2_ELEMENT> >
{
public:
// something here

int longestindex() {
int retval;
int maxSoFar = -1;
for (int i = 0; i < this->size(); ++i) {
int currentSize = this->operator[] (i).size ();
if (maxSoFar < currentSize) {
maxSoFar = currentSize;
retval = i;
}
}
return retval;
}

// longest returns the # of elements of the sub-vector
// with the most elements
int longest()
{
if (this->size() > 0)
{
// longestindex returns the index of the sub-vector
// with the most elements
int index = this->longestindex();
// return this->at(index).size(); // works
return (*this)[longestindex()].size(); // doesn't work
}
else
return -1;
}
} ;

int main () {
vec2<int> foo;
foo.push_back(std::vector<int> (3));
foo.push_back(std::vector<int> (8));
foo.push_back(std::vector<int> (5));
int retval = foo.longest();
}

I just took it as a simple coding exercise for the evening :-)
Post by Frank
Sorry, where are my manners...
many thanks for your effort.
You're welcome.
Stuart

Frank
2014-02-12 11:26:27 UTC
Permalink
Sorry, where are my manners...
many thanks for your effort.
Continue reading on narkive:
Loading...