Embarrassing problem with vector

T

T_P

I am teaching myself C++ and I am reading Lippman's book "Essential C+
+." I wrote a simple program that uses vectors. Here it is (the line
numbers are there for convenience, duh), I disclaim all copyright.
1 #include <iostream>
2 #include <vector>
3
4 using namespace std;
5
6 template<typename T>
7 void PrintVector(const vector<T> &vec)
8 {
9 vector<T>::const_iterator cur = vec.begin();
10 while (cur != vec.end()) {
11 cout << *cur << ", ";
12 ++cur;
13 }
14 cout << endl;
15 }
16
17 int main()
18 {
19 vector<int> vec;
20 for (int i = 0; i < 32; ++i) {
21 vec.push_back(i);
22 }
23 PrintVector(vec);
24 }



My compiler refuses to compile it, saying
vectest.cc: In function ‘void PrintVector(const std::vector<T,
std::allocator<_CharT> >&)’:
vectest.cc:9: error: expected `;' before ‘cur’
vectest.cc:10: error: ‘cur’ was not declared in this scope
vectest.cc: In function ‘void PrintVector(const std::vector<T,
std::allocator<_CharT> >&) [with T = int]’:
vectest.cc:23: instantiated from here
vectest.cc:9: error: dependent-name ‘std::vector::const_iterator’ is
parsed as a non-type, but instantiation yields a type
vectest.cc:9: note: say ‘typename std::vector::const_iterator’ if a
type is meant

I thought I did everything by the book, but seems so I didn't. :-/
What is the problem with this code? I pretty sure the problem lies on
the line 9...

Tuomas
 
A

Alf P. Steinbach

* T_P:
I am teaching myself C++ and I am reading Lippman's book "Essential C+
+." I wrote a simple program that uses vectors. Here it is (the line
numbers are there for convenience, duh), I disclaim all copyright.
1 #include <iostream>
2 #include <vector>
3
4 using namespace std;
5
6 template<typename T>
7 void PrintVector(const vector<T> &vec)
8 {
9 vector<T>::const_iterator cur = vec.begin();
10 while (cur != vec.end()) {
11 cout << *cur << ", ";
12 ++cur;
13 }
14 cout << endl;
15 }
16
17 int main()
18 {
19 vector<int> vec;
20 for (int i = 0; i < 32; ++i) {
21 vec.push_back(i);
22 }
23 PrintVector(vec);
24 }



My compiler refuses to compile it, saying
vectest.cc: In function ‘void PrintVector(const std::vector<T,
std::allocator<_CharT> >&)’:
vectest.cc:9: error: expected `;' before ‘cur’
vectest.cc:10: error: ‘cur’ was not declared in this scope
vectest.cc: In function ‘void PrintVector(const std::vector<T,
std::allocator<_CharT> >&) [with T = int]’:
vectest.cc:23: instantiated from here
vectest.cc:9: error: dependent-name ‘std::vector::const_iterator’ is
parsed as a non-type, but instantiation yields a type
vectest.cc:9: note: say ‘typename std::vector::const_iterator’ if a
type is meant

I thought I did everything by the book, but seems so I didn't. :-/
What is the problem with this code? I pretty sure the problem lies on
the line 9...

You're missing a 'typename', and I believe that's in the FAQ.

Please post the FAQ reference when/if you find it.

By the way, the line numbers are *not* a convenience. They introduce more work
for anyone wanting to compile your code. Please don't add line numbers in posted
code.


Cheers & hth.,

- Alf
 
T

T_P

Hi, Alf!
By the way, the line numbers are *not* a convenience. They introduce more work
for anyone wanting to compile your code. Please don't add line numbers in posted
code.

That's true. Didn't come to think that way.

Here's the code without line numbers.
#include <iostream>
#include <vector>

using namespace std;

template<typename T>
void PrintVector(const vector<T> &vec)
{
vector<T>::const_iterator cur = vec.begin();
while (cur != vec.end()) {
cout << *cur << ", ";
++cur;
}
cout << endl;
}

int main()
{
vector<int> vec;
for (int i = 0; i < 32; ++i) {
vec.push_back(i);
}
PrintVector(vec);
}

I located the FAQ at <http://www.parashift.com/c++-faq-lite/
templates.html>. I'll see if it has the answer to this problem.

T
 
J

Jerry Coffin

template<typename T>
void PrintVector(const vector<T> &vec)
{
vector<T>::const_iterator cur = vec.begin();
while (cur != vec.end()) {
cout << *cur << ", ";
++cur;
}
cout << endl;
}

Now that you've got your original problem figured out, consider using
std::copy instead of the explicit loop:

template <class T>
void PrintVector(const vector<T> &vec) {
copy(vec.begin(), vec.end(),
ostream_iterator<T>(cout, ", "));
cout << endl;
}

Of course, you probably don't really want the ", " after the last
element, in which case you'd want to replace the ostream_iterator
with the infix_ostream_iterator that was posted here a few months
ago. There's also little real reason to restrict the function to
working with a vector -- it could just as well work with any
collection that provides 'begin()' and 'end()' member functions:

#include <vector>
#include <algorithm>
#include <iostream>
#include "infix_iterator.h"

template <class Coll>
void PrintColl(const Coll col) {
std::copy(col.begin(), col.end(),
infix_ostream_iterator<typename Coll::value_type>
(std::cout, ", "));
std::cout << std::endl;
}

int main() {
std::vector<int> vec;

for (int i=0; i<16; i++)
vec.push_back(i);

PrintColl(vec);
return 0;
}

Result:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
 
A

Anand Hariharan

(...)
Now that you've got your original problem figured out, consider using
std::copy instead of the explicit loop:

template <class T>
void PrintVector(const vector<T> &vec) {
copy(vec.begin(), vec.end(),
ostream_iterator<T>(cout, ", "));
cout << endl;
}

Of course, you probably don't really want the ", " after the last
element, in which case you'd want to replace the ostream_iterator with
the infix_ostream_iterator that was posted here a few months ago.

Are you referring to <[email protected]>? It
contains an implementation although you refer to one of your earlier
posts.


(...)
template <class Coll>
void PrintColl(const Coll col) {

Am pretty sure you meant

template <class Coll>
void PrintColl(const Coll & col) {

so that a copy is avoided.
 
J

Juha Nieminen

Jerry said:
Now that you've got your original problem figured out, consider using
std::copy instead of the explicit loop:

One problem which I see with many STL algorithms is that they are
often awkard and laborious to use, even though they *should* be simple
(ideally most usages would be one-liners).

The problem is that if you want to specify *what* to do with each
element being processed, you have to write quite a lot of code (usually
a separate function or functor). Writing an explicit loop is actually
less work than using the STL algorithm in many cases.

Fortunately this problem will (hopefully) be solved with the next C++
standard and its lambda functions (which will allow you to write the
function implementation right there, as the parameter to the STL
algorithm, making it as easy as, if not even easier than, writing an
explicit loop).
 
J

Jerry Coffin

J

Jerry Coffin

One problem which I see with many STL algorithms is that they are
often awkard and laborious to use, even though they *should* be simple
(ideally most usages would be one-liners).

Quite true -- I'm fairly careful to use the algorithms only when/if
they seem (at least to me) to make the code more readable, not less
so. In this case, I think it does. I've certainly seen things like:

for_each( m.begin(), m.end(),
CallFuncOn2nd_t< tMap::value_type,
binder2nd< mem_fun1_ref_t< void, d, int> > >(
bind2nd( mem_fun_ref( &d::setIntMember ), 4 ) ) );

and in such a case, I think an explicit loop is generally a better
choice. In fact, if you get down to it, I've only ever used mem_fun,
mem_fun_ref, bind2nd, etc., in code written to show how to use them
(usually with a warning that I doubt that code is the best way to do
things). Boost adds enough extras (bind, lambda) to make such things
work out more often, but overall I have to agree: a lot of this won't
really be clean enough to be worthwhile until we can use lambdas.
The problem is that if you want to specify *what* to do with each
element being processed, you have to write quite a lot of code (usually
a separate function or functor). Writing an explicit loop is actually
less work than using the STL algorithm in many cases.

Right -- just in this case, that "what" had to be specified in an
operator<< in either case, so using the standard algorithm didn't
really add any work.
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top