473,756 Members | 4,863 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 4542
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
2635
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
7383
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
9930
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9716
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 captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9716
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7116
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 instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6410
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5180
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3676
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
2
3185
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2542
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.