By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,089 Members | 2,191 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,089 IT Pros & Developers. It's quick & easy.

Returning iterator from template class

P: n/a
Hi All,

I'm trying to write a wrapper class for std::vector to extend some of
its functionality. The problem I'm getting into is returning an
iterator type from a member function. Here is the essense of what I'm
trying to do:

//-------code-------

#include <vector>
using namespace std;

template <class T>
class ExtendedVector
{
private:
vector<T> vals;
public:
vector<T>::iterator begin()
{
return vals.begin();
}
};

//-------end code-------

However, this gives me the error

error: expected ';' before 'begin'

What's the proper way to achieve what I'm trying to do?

May 31 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a

jois.de.vi...@gmail.com wrote:

Implement thus:
template <class T>
class ExtendedVector
{
private:
vector<T> vals;
public: // the following not only saves typing but allows you to
implement
// with a different object type other than vector...just
change the defs here
// and clients will fall in line so long as they don't try
to bypass your interface.

typedef typename vector<T>::iterator iterator_t;
typedef typename vector<T>::const_iterator const_iterator_t;
iterator_t begin() // changed return type to above typedefs
{
return vals.begin();
} // implement for const objects...
const_iterator_t begin() const { return vals.begin(); } };

//-------end code-------


ExtendedVector<T> t;
ExtendedVector<T>::iterator_t it;

May 31 '06 #2

P: n/a

<jo***********@gmail.com> wrote in message
news:11*********************@g10g2000cwb.googlegro ups.com...
Hi All,

I'm trying to write a wrapper class for std::vector to extend some of
its functionality. The problem I'm getting into is returning an
iterator type from a member function. Here is the essense of what I'm
trying to do:

//-------code-------

#include <vector>
using namespace std;

template <class T>
class ExtendedVector
{
private:
vector<T> vals;
public:
vector<T>::iterator begin()

typename vector<T>::iterator begin()

Regards,

Sumit.
--
Sumit Rajan <su*********@gmail.com>
May 31 '06 #3

P: n/a
>
typedef typename vector<T>::iterator iterator_t;
typedef typename vector<T>::const_iterator const_iterator_t;
iterator_t begin() // changed return type to above typedefs
{
return vals.begin();
}

// implement for const objects...
const_iterator_t begin() const { return vals.begin(); }


Wonderful! I guess my next question is, how did you know to do that? At
this point I don't even know what the 'typedef typename' part of the
above code snippet means. More specifically I suppose is, where can I
get a detailed discussion about templates. Any recommendations on
books? web sites?

May 31 '06 #4

P: n/a

jo***********@gmail.com wrote:
Hi All,

I'm trying to write a wrapper class for std::vector to extend some of
its functionality. The problem I'm getting into is returning an
iterator type from a member function. Here is the essense of what I'm
trying to do:

//-------code-------

#include <vector>
using namespace std;

template <class T>
class ExtendedVector
{
private:
vector<T> vals;
public:
vector<T>::iterator begin()
{
return vals.begin();
}
};

//-------end code-------

However, this gives me the error

error: expected ';' before 'begin'

What's the proper way to achieve what I'm trying to do?


You need to point out that the vector<T>::iterator is typename.
If you want to extend the vector, inheritance is better than
composition in your case.

May 31 '06 #5

P: n/a

<jo***********@gmail.com> wrote in message
news:11*********************@i39g2000cwa.googlegro ups.com...
get a detailed discussion about templates. Any recommendations on
books? web sites?


Book Recommendation:
"C++ Templates" by David Vandevoorde, Nicolai M. Josuttis.

Regards,
Sumit.
--
Sumit Rajan <su*********@gmail.com>
May 31 '06 #6

P: n/a
jo***********@gmail.com wrote:
Wonderful! I guess my next question is, how did you know to do that? At
this point I don't even know what the 'typedef typename' part of the
above code snippet means. More specifically I suppose is, where can I
get a detailed discussion about templates. Any recommendations on
books? web sites?


Basically, the "typename" keyword is used for what are called "dependant
names" in a template, which tells the compiler that what follows it is
the name of a type and not e.g. a static object of a class.

As always, the FAQ is a good starting point:
http://www.parashift.com/c++-faq-lite/

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
May 31 '06 #7

P: n/a

jo***********@gmail.com wrote:

typedef typename vector<T>::iterator iterator_t;
typedef typename vector<T>::const_iterator const_iterator_t;
iterator_t begin() // changed return type to above typedefs
{
return vals.begin();
}

// implement for const objects...
const_iterator_t begin() const { return vals.begin(); }


Wonderful! I guess my next question is, how did you know to do that? At
this point I don't even know what the 'typedef typename' part of the
above code snippet means. More specifically I suppose is, where can I
get a detailed discussion about templates. Any recommendations on
books? web sites?


Markus answered the question but it may have been a bit confusing.
Without the 'typename' keyword the compiler will think you are trying
to reference a value within the class:

class X
{
public: enum { v };
};

int val = X::v;

is more along the lines of what it thinks you mean because it can't
actually get complete information about the template at this point and
doesn't know what you are talking about. If it looks like a variable
it is unless it isn't....and right now it doesn't know that it isn't.

So you explicitly say, "The next name I use is a type name, not a
variable or value."

Really you are seing this:

typedef type new_name;

where type is "typename temp<type>::internal_type".

I did the typedef to abstract the internal representation of the class
so that if vector becomes the wrong container it can be changed without
affecting clients. They will have to be recompiled of course, but you
won't have to do a bunch of editing outside the class to reflect
changes done to its insides. You could even return your own iterator
that might be a simple pointer at some point. It isn't necissary to do
the typedefs, but it is good practice. All clients need to know is
that something that has the interface of an iterator will be returned
from those functions...they don't need to know exactly what
implementation of an iterator they are getting (although it would be
important to know forward/reverse/random/insert...etc...more may be
necissary to truely encapsulate your type).

You can also read Bruce Eckel's Thinking in C++ V2 online and this
explains what typename is and where it needs to be used.

May 31 '06 #8

P: n/a

dan2online wrote:
You need to point out that the vector<T>::iterator is typename.
If you want to extend the vector, inheritance is better than
composition in your case.


As a rule inheritance should be used only when necissary. It may well
be the case here but nothing in the OP indicates that.

May 31 '06 #9

P: n/a
dan2online wrote:
If you want to extend the vector, inheritance is better than
composition in your case.

Eehhhhh.

It's 'riskily dangerous' to inherit from vector<T> (or any other
standard containers) because they don't have virtual destructors. No
virtual destructors mean that if you ever end up storing your
super_vector<T> as a vector<T>*, and then delete that pointer, /the
universe explodes/. Or near enough.

There are few 'never's in programming, but as a rule of thumb, I have to
stop and think real hard about extending a class with no virtual destructor.
Jack Saalweachter
May 31 '06 #10

P: n/a

Jack Saalweachter wrote:
dan2online wrote:
If you want to extend the vector, inheritance is better than
composition in your case.

Eehhhhh.

It's 'riskily dangerous' to inherit from vector<T> (or any other
standard containers) because they don't have virtual destructors. No
virtual destructors mean that if you ever end up storing your
super_vector<T> as a vector<T>*, and then delete that pointer, /the
universe explodes/. Or near enough.

There are few 'never's in programming, but as a rule of thumb, I have to
stop and think real hard about extending a class with no virtual destructor.


Well it doesn't have any virtual functions at all so inheriting from it
is questionable to begin with but obviously it can't be used places
where vector is used since the behavior couldn't be relied upon.
Inheritance in this case would be a shortcut...but like you say, a
dangerous one.

Really, without knowing why this user wants to "extend" vector we don't
really know if that would be the right way to solve their given problem.

May 31 '06 #11

P: n/a
Jack Saalweachter wrote:
dan2online wrote:
If you want to extend the vector, inheritance is better than
composition in your case.

Eehhhhh.

It's 'riskily dangerous' to inherit from vector<T> (or any other
standard containers) because they don't have virtual destructors. No
virtual destructors mean that if you ever end up storing your
super_vector<T> as a vector<T>*, and then delete that pointer, /the
universe explodes/. Or near enough.


Use private inheritance. Most references indicate that private
inheritance represents the concept "is-implemented-in-terms-of".
May 31 '06 #12

P: n/a
Jack Saalweachter wrote:
dan2online wrote:
If you want to extend the vector, inheritance is better than
composition in your case.

Eehhhhh.

It's 'riskily dangerous' to inherit from vector<T> (or any other
standard containers) because they don't have virtual destructors. No
virtual destructors mean that if you ever end up storing your
super_vector<T> as a vector<T>*, and then delete that pointer, /the
universe explodes/. Or near enough.

There are few 'never's in programming, but as a rule of thumb, I have to
stop and think real hard about extending a class with no virtual
destructor.


May I direct your attention to

std::unary_function

or

std::iterator

These classes are explicitly meant to be inherited from, yet they do not
have a virtual destructor.

In general, whether you need polymorphic pointers is very much dependent on
your field of programming -- I have almost no use for runtime polymorphism.
However, I do have a need to, e.g., distinguish ordinary containers from
vectors that support arithmetic operations:
template < typename T >
class math_vector : public std::vector< T > {
public:

math_vector ( void )
: std::vector< T > ()
{}

template < typename A >
math_vector ( A a )
: std::vector< T > ( a )
{}

template < typename A, typename B >
math_vector ( A a, B b )
: std::vector< T > ( a, b )
{}

template < typename A, typename B, typename C >
math_vector ( A a, B b, C c )
: std::vector< T > ( a, b, c )
{}

template < typename A, typename B, typename C, typename D >
math_vector ( A a, B b, C c, D d )
: std::vector< T > ( a, b, c, d )
{}

}; // math_vector<>

Now, you can implement vector arithmetic along the following lines:

template < typename T >
math_vector< T > operator+= ( math_vector< T > & u,
math_vector< T > const & v ) {
typename math_vector< T >::const_iterator v_iter = v.begin();
for ( typename math_vector< T >::iterator u_iter = u.begin();
u_iter != u.end();
++ u_iter, ++ v_iter ) {
*u_iter += *v_iter;
}
return( u );
}

and the overload does not extend to all vectors but only those that are
flagged as math_vectors in the program. Here, std::vector is used like a
policy class and its use is an implementation detail of math_vector.
It is true that you cannot use pointers to std::vector polymorphically.
Well, so just don't do that. However, to infer that inheritance should be
limited to classes with virtual destructors is an over-generalization: in
fact, policy based design uses inheritance quite extensively, yet most
policy classes have no virtual destructors.
Best

Kai-Uwe Bux
May 31 '06 #13

P: n/a
On 31 May 2006 11:42:00 -0700, "Noah Roberts" <ro**********@gmail.com>
wrote:
Without the 'typename' keyword the compiler will think you are trying
to reference a value within the class:

class X
{
public: enum { v };
};

int val = X::v;

is more along the lines of what it thinks you mean because it can't
actually get complete information about the template at this point and
doesn't know what you are talking about. If it looks like a variable
it is unless it isn't....and right now it doesn't know that it isn't.

So you explicitly say, "The next name I use is a type name, not a
variable or value."


The funny thing is that compilers had no problem to distinguish those
cases for many years. Only in recent versions they force the user to
add a 'typename' and cause much confusion by giving an irrelevant
error message. It's probably more a C++ Standard problem than a
compiler problem.

Best regards,
Roland Pibinger
May 31 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.