template vector, incomplete type error

I

imutate

Hi,
I am migrating some std::vectors to use a template instead, but I get
an incomplete type error in a struct declaration.

#include <vector>

template < typename T >
class Vec : public std::vector< T > {
public:
Vec():Vec<T>() { }
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};


typedef Vec<double> vecdbl;
typedef Vec<vecdbl> matdbl;


#include "matvec.h"
// that is it above

typedef vecdbl memvec;

struct felt
{
...
memvec m; // <- incomplete type error
 
G

Greg Comeau

Hi,
I am migrating some std::vectors to use a template instead, but I get
an incomplete type error in a struct declaration.

#include <vector>

template < typename T >
class Vec : public std::vector< T > {
public:
Vec():Vec<T>() { }
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};


typedef Vec<double> vecdbl;
typedef Vec<vecdbl> matdbl;


#include "matvec.h"
// that is it above

typedef vecdbl memvec;

struct felt
{
..
memvec m; // <- incomplete type error

I don't understand Vec():Vec<T>() and probably you're compiler
doesn't either eventually makeing Vec<T> incomplete classes
because of that problem.
 
K

Kai-Uwe Bux

#include <vector>

template < typename T >
class Vec : public std::vector< T > {
public:
Vec():Vec<T>() { }

Vec() : std::vector said:
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }

& operator[](int i) { return this->at(i); }
const T& operator[](int i ) const { return at(i); }

const T& operator[](int i ) const { return this->at(i); }
};


typedef Vec<double> vecdbl;
typedef Vec<vecdbl> matdbl;


#include "matvec.h"
// that is it above

typedef vecdbl memvec;

struct felt
{
..
memvec m;  // <- incomplete type error


Best

Kai-Uwe Bux
 
G

Greg Comeau

Hi,
I am migrating some std::vectors to use a template instead, but I get
an incomplete type error in a struct declaration.

#include <vector>

template < typename T >
class Vec : public std::vector< T > {
public:
Vec():Vec<T>() { }
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};


typedef Vec<double> vecdbl;
typedef Vec<vecdbl> matdbl;


#include "matvec.h"
// that is it above

typedef vecdbl memvec;

struct felt
{
..
memvec m; // <- incomplete type error

I don't understand Vec():Vec<T>() and probably you're compiler
doesn't either eventually makeing Vec<T> incomplete classes
because of that problem.

Also on a different aspect: std::vector was not written to be
derived from.
 
I

imutate

I don't understand Vec():Vec<T>() and probably you're compiler
doesn't either eventually makeing Vec<T> incomplete classes
because of that problem.

I tried these but it gives same error

template < typename T >
class Vec : public std::vector< T > {
public:
Vec(): std::vector<T>() { }
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};

and

template < typename T >
class Vec : public std::vector< T > {
public:
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};

Do I need std:: infront of anything else ? What is the "(s)" about ?
 
K

Kai-Uwe Bux

Greg said:
Hi,
I am migrating some std::vectors to use a template instead, but I get
an incomplete type error in a struct declaration.

#include <vector>

template < typename T >
class Vec : public std::vector< T > {
public:
Vec():Vec<T>() { }
Vec( int s ) : std::vector<T>(s) { }
T& operator[](int i) { return at(i); }
const T& operator[](int i ) const { return at(i); }
};


typedef Vec<double> vecdbl;
typedef Vec<vecdbl> matdbl;


#include "matvec.h"
// that is it above

typedef vecdbl memvec;

struct felt
{
..
memvec m; // <- incomplete type error

I don't understand Vec():Vec<T>() and probably you're compiler
doesn't either eventually makeing Vec<T> incomplete classes
because of that problem.

Also on a different aspect: std::vector was not written to be
derived from.

If you look at the OP's code, the template class Vec<T> is clearly a
debugging tool: I would bet that the intended use is to redefine some
typedefs that currently go to std::vector to hunt down some out of bounds
errors. Once those are fixed, the typedef will hopefully be changed back to
std::vector in production code. I cannot see any harm in this little trick.

Of course, a full-fledged debugging vector (e.g., whose iterators would
guard against invalidation) would be even better.


Best

Kai-Uwe Bux
 
I

imutate

Greg said:
Also on a different aspect: std::vector was not written to be
derived from.
--

Why was I recommended to wrap this in a template in the first place ?
 
K

Kai-Uwe Bux

Why was I recommended to wrap this in a template in the first place ?

To cut a long story short: std::vector does not have a virtual destructor.
That implies that you get undefined behavior if you use a std::vector<T>*
polymorphically and you delete an object of a derived class through this
pointer. Another source of surprises is that references to derived objects
will silently convert to references of type std::vector<T>.

Certain people think that it is therefore a BadIdea(tm) to ever inherit
publicly from std::vector<T>. Others think it's ok as long as you know
about the possible traps. In your case, it looks as though you use this
inheritance just as a temporary debugging tool and there is probably no
harm. Also, you could go back to std::vector<T> in production code once
the out of bounds errors have been found. In principle, you should be able
to do the switch with a simple typedef in your code.

Inheriting from std::vector<T> can be tricky. That does not imply it is
always bad. But you have to be aware of the difficulties that can arise.


Best

Kai-Uwe Bux
 
I

imutate

Kai-Uwe Bux said:
Inheriting from std::vector<T> can be tricky. That does not imply it is
always bad. But you have to be aware of the difficulties that can arise.


Best

Kai-Uwe Bux

Thanks, I'll check this out. Does this count as inheriting ?

class myc
{
std::vector<double> x;
...
 
K

Kai-Uwe Bux

Thanks, I'll check this out. Does this count as inheriting ?

class myc
{
std::vector<double> x;
..

Nope, that is usually called composition. The drawback is that you have to
write tons of boilerplate code to forward all the member functions.

Also, I did not intend to scare you away from public inheritance in this
particular case. If you do not use pointers to std::vector polymorphically
(and you don't have a reason to do that anyhow), you will almost certainly
be fine.

To complete the picture, you might want to read up on private inheritance:

class my_vector : private std::vector<double> {

using iterator;
using ...
// tons of using declarations forwarding all members that we want.

};

This avoids the pitfalls of public inheritance and is less boilerplate code
than composition.


Best

Kai-Uwe Bux
 
G

Gianni Mariani

Greg Comeau wrote:
....
Also on a different aspect: std::vector was not written to be
derived from.

In what way was it not written to be derived from ?

(I hope you don't say that it does not have a virtual destructor...)
 
G

Greg Comeau

Greg Comeau wrote:
...

In what way was it not written to be derived from ?

(I hope you don't say that it does not have a virtual destructor...)

From the get go, except for I guess iostreams, the intent
of the containters was to be stand alone self contained entities.

In what way was it written to be derived from ?
It is purposely designed to be extensible, but through templates,
which is a different type of relationship approach.
 
G

Gianni Mariani

Greg Comeau wrote:
....
In what way was it written to be derived from ?
It is purposely designed to be extensible, but through templates,
which is a different type of relationship approach.

So there is nothing specific that makes the classes "designed" to not be
inherited.

So there should be no reason that these classes can't be inherited from.
(modulo all the regular gotchas - slicing dicing and deleting from the
wrong pointer etc...)
 
G

Greg Comeau

Greg Comeau wrote:
...

So there is nothing specific that makes the classes "designed" to not be
inherited.

So there should be no reason that these classes can't be inherited from.
(modulo all the regular gotchas - slicing dicing and deleting from the
wrong pointer etc...)

What? So except for the obvious normal stuff there is no reason. Uh-huh.

I guess I don't understand what you don't understand. I am not a
C++ standard library expert, but it seems to me:
* The authors have said so.
* All useful data in vector (and perhaps unuseful ones too) is private
(not that it would be public but perhaps at least protected).
* There is no virtuals.
* It seems to me that there is a disconnect between related things
such as iterators, which need to go hand in hand with it. I could be wrong.

IOWs, except for an instrumentation example given earlier (it had not
dawned on me that's what the OP was doing duh) there is not really all
that much that could be gained. So it seems to me that the extensibility
is as a template. I would probably expect a particular instantiation
to be derived from if anything but even that I guess I would think about.
Also, in such cases where a design needs to be bent, or enhanced,
I often find that more superior solutions can come about in other ways
(containment (which isn't perfect either), private inheritance,
the typedef mentioned earlier, even regular (thought perhaps template'd)
functions (aka "free functions", etc.).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top