473,587 Members | 2,321 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

cout << vector<string>


In the boost::program_ options tutorial, the author included the following
code:
cout << "Input files are: "
<< vm["input-file"].as< vector<string()
<< "\n";
Basically, he is trying to print a vector of string, in one line. I could
not get this compile (let alone run). To get it to compile and run, I had
to re-write it as:
vector<stringv = vm["input-file"].as< vector<string() ;

vector<string>: :const_iterator i;

for ( i = v.begin();
i != v.end();
++i )
{
cout << *citer << " ";
}
Does anyone know if the original line of code is correct? If so, what was I
missing?

Nov 6 '08 #1
42 4504
On Nov 6, 11:06*pm, "barcarolle r" <barcarol...@mu sic.netwrote:
In the boost::program_ options tutorial, the author included the following
code:

* * cout << "Input files are: "
* * * * *<< vm["input-file"].as< vector<string()
* * * * *<< "\n";

Basically, he is trying to print a vector of string, in one line. *I could
not get this compile (let alone run). *To get it to compile and run, I had
to re-write it as:

* * vector<stringv = vm["input-file"].as< vector<string() ;

* * vector<string>: :const_iterator i;

* * for ( * i *= v.begin();
* * * * * * i != v.end();
* * * * * ++i )
* * {
* * * * cout << *citer << " ";
* * }

Does anyone know if the original line of code is correct? *If so, what was I
missing?
The example probably assumes there is an overloaded operator<<() for
std::ostream and std::vector<>, something like this:

#include <ostream>
#include <iterator>
#include <algorithm>

namespace std {

template<class A1, class A2>
ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
{
copy(vec.begin( ), vec.end(), ostream_iterato r<A1>(s, "
"));
return s;
}

}

--
Max
Nov 7 '08 #2
On 2008-11-06 18:06:47 -0500, "barcarolle r" <ba*********@mu sic.netsaid:
>
In the boost::program_ options tutorial, the author included the following
code:
cout << "Input files are: "
<< vm["input-file"].as< vector<string()
<< "\n";

Does anyone know if the original line of code is correct?
Not in standard C++.
If so, what was I
missing?
Either some code that was mentioned somewhere in the tutorial, or a
better tutorial.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Nov 7 '08 #3
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma************ ***@gmail.comsa id:
>
The example probably assumes there is an overloaded operator<<() for
std::ostream and std::vector<>, something like this:

#include <ostream>
#include <iterator>
#include <algorithm>

namespace std {

template<class A1, class A2>
ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
{
copy(vec.begin( ), vec.end(), ostream_iterato r<A1>(s, "
"));
return s;
}

}
Which has undefined behavior. You can only add template specializations
to namespace std when they depend on user-defined types.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Nov 7 '08 #4
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma************ ***@gmail.comsa id:
>The example probably assumes there is an overloaded operator<<() for
std::ostream and std::vector<>, something like this:
> namespace std {

template<class A1, class A2>
ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
Which has undefined behavior. You can only add template specializations
to namespace std when they depend on user-defined types.
The correct alternative, AIUI:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}

int main() {
int const ints[] = { 1, 2, 3, 4 };
std::cout << std::vector<int >( ints, ints + 4 ) << '\n';
}
Nov 7 '08 #5
Jeff Schwab wrote:
template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}
Is there some advantage of that code over a shorter and simpler:

template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
out << v[i] << " ";
out << v.back();
return out;
}
Nov 7 '08 #6
Juha Nieminen wrote:
Jeff Schwab wrote:
>template<typen ame T>
std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}

Is there some advantage of that code over a shorter and simpler:

template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
Nit: std::size_t is not guaranteed to be vector::size_ty pe.
out << v[i] << " ";
out << v.back();
I think, v.back() has undefined behavior if the v is empty.
return out;
}

Best

Kai-Uwe Bux
Nov 7 '08 #7
Juha Nieminen wrote:
Jeff Schwab wrote:
>template<typen ame T>
std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}

Is there some advantage of that code over a shorter and simpler:

template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
out << v[i] << " ";
out << v.back();
return out;
}
The use of the standard algorithm (rather than a hand-rolled loop) helps
separate the different levels of abstraction. In your example, the code
that works with an individual datum of type T is all mixed up with the
code that works with the vector as a whole. There are decent
discussions of this in Effective STL (Scott Meyers) and Clean Code
(Robert Martin).
Nov 7 '08 #8
On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush ...@gmail.comsa id:
The example probably assumes there is an overloaded operator<<() for
std::ostream and std::vector<>, something like this:
namespace std {
template<class A1, class A2>
ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
Which has undefined behavior. You can only add template specializations
to namespace std when they depend on user-defined types.
The correct alternative, AIUI:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
template<typena me T>
std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}
int main() {
int const ints[] = { 1, 2, 3, 4 };
std::cout << std::vector<int >( ints, ints + 4 ) << '\n';
}
Correct in what sense? It's OK for simple test, like this, but
it's certainly not something you'd allow in production code.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 7 '08 #9
Jeff Schwab wrote:
Juha Nieminen wrote:
>Jeff Schwab wrote:
>>template<type name T>
std::ostrea m& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
if (!v.empty()) {
typedef std::ostream_it erator<Tout_ite r;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
}
return out;
}

Is there some advantage of that code over a shorter and simpler:

template<typen ame T>
std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
out << v[i] << " ";
out << v.back();
return out;
}

The use of the standard algorithm (rather than a hand-rolled loop) helps
separate the different levels of abstraction. In your example, the code
that works with an individual datum of type T is all mixed up with the
code that works with the vector as a whole. There are decent
discussions of this in Effective STL (Scott Meyers) and Clean Code
(Robert Martin).
You know, the code I posted has exactly the same problem I pointed out
in yours: the level of abstraction is mixed. I was imagining the work
split neatly between two standard utilities:

1. std::copy handles iteration through the vector.
2. std::ostream_it erator handles the output of each element.

The problem is that the last item should be output slightly differently
from the others, so the code can't be factored quite so neatly with
those utilities. The semantic messiness is reflected in the code: the
explicit check for an empty vector (which should be irrelevant at that
level), the hard-coded -1, and the call of v.back() are all symptoms.
The worst issue is the manual output of the last vector element, which
should be the ostream_iterato r's job. You could improve the situation a
little by delegating to another ostream_iterato r:

*out_iterator( out ) = v.back();

You would still be doing the copy algorithm's job, though. You could
avoid that by calling copy twice, e.g:

copy(v.begin(), v.end()-1, out_iter( out, " " ));
copy(v.end()-1, v.end(), out_iter( out ));

That's silly, though, because it implies a loop over just one element.
You don't need the full copy algorithm; it's just that std::copy is the
closest thing to what we need that happens to be in the standard library.

What's really needed is a set of utilities that better fit the natural
division of the problem. The following seems to me like a reasonable
solution: Use a custom (but generic) copy algorithm that implicitly
gives the last element special treatment, and use two separate output
iterators:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

/* Assign all but the last element of [pos, end) to *out, and assign
* the last element to *fin. */

template<typena me Fwd_iter, typename Out_iter>
void final_copy(
Fwd_iter pos, Fwd_iter end,
Out_iter out, Out_iter fin) {
if (pos != end) {
for (Fwd_iter next = pos; ++next != end; pos = next) {
*out = *pos;
++out;
}
*fin = *pos;
++fin;
}
}

template<typena me T>
std::ostream& operator<<(
std::ostream& out, std::vector<Tco nst& v) {
typedef std::ostream_it erator<Tout_ite r;
final_copy(
v.begin(), v.end(),
out_iter( out, " " ),
out_iter( out ));
return out;
}

int main() {
int const ints[] = { 1, 2, 3, 4 };
std::cout << std::vector<int >( ints, ints + 4 ) << '\n';
}
The output operator for the vector still has two responsibilitie s:
Configuration/composition of the utilities to perform the actual output,
and implementation of the standard conventions for operator<<, e.g.
returning the output stream by reference. It probably should be further
refactored along those lines:

template<typena me T>
void print(std::ostr eam& out, std::vector<Tco nst& v) {
typedef std::ostream_it erator<Tout_ite r;
final_copy(
v.begin(), v.end(),
out_iter( out, " " ),
out_iter( out ));
}

template<typena me T>
std::ostream& operator<<(
std::ostream& out, std::vector<Tco nst& v) {
print(out, v);
return out;
}

The only thing left that I don't like is the configuration code embedded
in the print function, specifically the hard-coded " ". The best
solution (for non-trivial applications) might be a traits class that
tells what the separator should be between elements, and defaults to " "
or "\n":

out_iterator( out, separator<T>::v alue );
Nov 7 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2623
by: ehui928 | last post by:
hi, everybody I am a newbie in STL. When I compile the following program under gcc4.0, I got a the following errors. I wonder whether the form of list< vector<string> > is correct in STL ? // test.cpp #include <iostream> #include <fstream> #include <vector> #include <string>
6
7358
by: Mr. K.V.B.L. | last post by:
I want to start a map with keys but an empty vector<string>. Not sure what the syntax is here. Something like: map<string, vector<string MapVector; MapVector.insert(make_pair("string1", new vector<string>)); MapVector.insert(make_pair("string2", new vector<string>)); MapVector.insert(make_pair("string3", new vector<string>));
0
7918
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
8340
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
8220
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5713
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3840
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3875
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2353
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1452
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1185
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.