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

cout << vector<string>

P: n/a

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
Share this Question
Share on Google+
42 Replies


P: n/a
On Nov 6, 11:06*pm, "barcaroller" <barcarol...@music.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<<(ostream& s, vector<A1, A2const& vec)
{
copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
return s;
}

}

--
Max
Nov 7 '08 #2

P: n/a
On 2008-11-06 18:06:47 -0500, "barcaroller" <ba*********@music.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

P: n/a
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma***************@gmail.comsaid:
>
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<<(ostream& s, vector<A1, A2const& vec)
{
copy(vec.begin(), vec.end(), ostream_iterator<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

P: n/a
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma***************@gmail.comsaid:
>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<<(ostream& 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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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

P: n/a
Jeff Schwab wrote:
template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
out << v[i] << " ";
out << v.back();
return out;
}
Nov 7 '08 #6

P: n/a
Juha Nieminen wrote:
Jeff Schwab wrote:
>template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)
Nit: std::size_t is not guaranteed to be vector::size_type.
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

P: n/a
Juha Nieminen wrote:
Jeff Schwab wrote:
>template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& 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

P: n/a
On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcenter.comwrote:
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& 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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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 objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 7 '08 #9

P: n/a
Jeff Schwab wrote:
Juha Nieminen wrote:
>Jeff Schwab wrote:
>>template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& 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_iterator 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_iterator's job. You could improve the situation a
little by delegating to another ostream_iterator:

*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<typename 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<typename T>
std::ostream& operator<<(
std::ostream& out, std::vector<Tconst& v) {
typedef std::ostream_iterator<Tout_iter;
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 responsibilities:
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<typename T>
void print(std::ostream& out, std::vector<Tconst& v) {
typedef std::ostream_iterator<Tout_iter;
final_copy(
v.begin(), v.end(),
out_iter( out, " " ),
out_iter( out ));
}

template<typename T>
std::ostream& operator<<(
std::ostream& out, std::vector<Tconst& 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>::value );
Nov 7 '08 #10

P: n/a
James Kanze wrote:
On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcenter.comwrote:
>Pete Becker wrote:
>>On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& 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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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.
Correct in the sense that it implements the OP's intent, and is allowed
by the standard. As far as using it in production code... Ad hoc
output of this sort only really comes up for debugging purposes. If you
don't even think it's OK for debug, I'd love to know your suggested
alternative.
Nov 7 '08 #11

P: n/a
rio

"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org...
Juha Nieminen wrote:
>Jeff Schwab wrote:
>>template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)

Nit: std::size_t is not guaranteed to be vector::size_type.
so could be
std::size_t != vector::size_type
and what could happen if in the definition
size_t sii=big;
int a[sii];
vector<int b(a, a+sii);
> 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 9 '08 #12

P: n/a
rio

"Jeff Schwab" <je**@schwabcenter.comha scritto nel messaggio
news:Q7******************************@giganews.com ...
Pete Becker wrote:
>On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma***************@gmail.comsaid:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
what is the meaning of "out << v.back();"
why not write above only?
copy(v.begin(), v.end(), out_iter( out, " " ));

why it is not easy?

is it not better the "operator<<" defined below?

#include <stdio.h>
#include <iostream.h>
#include <iterator.h>
#include <vector.h>

template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<T>const& v)
{size_t i;
for(i=0; i<v.size(); ++i)
out<<v[i]<<" ";
return out;
}

int main()
{int ints[]={1,2,3,4}, inty2[100]={0}, i;
std::vector<int vettore(inty2, inty2+100);
std::vector<int vettor1(100);

for(i=0; i<90; ++i)
vettor1[i]=i;

std::cout << std::vector<int>(ints,ints+4) << '\n';
std::cout << vettore << '\n';
std::cout << "Vettor1" << vettor1 << '\n';

getchar();
}

the above seems ok what not seems ok to me that this
"
std::vector<int vettor1;

for(i=0; i<90; ++i)
vettor1[i]=i;
"
here goes in segmentation fault
is not vector1 self sizabile?

than how you are sure that *all* the allocations have its deallocation?
for example it seems "std::vector<int>(ints,ints+4)"
copy in new memory the array ints[0..3]
and than it has to deallocate it but when and where
}
return out;
}

int main() {
int const ints[] = { 1, 2, 3, 4 };
std::cout << std::vector<int>( ints, ints + 4 ) << '\n';
}


Nov 9 '08 #13

P: n/a
rio

"rio" <a@b.cha scritto nel messaggio
news:49***********************@reader5.news.tin.it ...
>
"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org...
>Juha Nieminen wrote:
>>Jeff Schwab wrote:
template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)

Nit: std::size_t is not guaranteed to be vector::size_type.
i know max(std::size_t) >= max(vector::size_type)
i know v.size()-1<=max(vector::size_type) <= max(std::size_t)

so size_t is ok

Nov 10 '08 #14

P: n/a
rio wrote:
>
"rio" <a@b.cha scritto nel messaggio
news:49***********************@reader5.news.tin.it ...
>>
"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org.. .
>>Juha Nieminen wrote:

Jeff Schwab wrote:
template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
for(std::size_t i = 0; i < v.size()-1; ++i)

Nit: std::size_t is not guaranteed to be vector::size_type.

i know max(std::size_t) >= max(vector::size_type)
Could you provide a pointer into the standard to backup that claim? or are
you making a statement about a particular platform?

i know v.size()-1<=max(vector::size_type) <= max(std::size_t)

so size_t is ok

Best

Kai-Uwe Bux
Nov 10 '08 #15

P: n/a
On Nov 7, 12:17*pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:


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<<(ostream& s, vector<A1, A2const& vec)
* * * * {
* * * * * * copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
* * * * * * return s;
* * * * }
* * }

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

On practice it works just fine as long as One Definition Rule is not
violated.

--
Max
Nov 10 '08 #16

P: n/a
On Nov 7, 7:21 pm, Jeff Schwab <j...@schwabcenter.comwrote:
James Kanze wrote:
On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcenter.comwrote:
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& 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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
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.
Correct in the sense that it implements the OP's intent, and
is allowed by the standard. As far as using it in production
code... Ad hoc output of this sort only really comes up for
debugging purposes. If you don't even think it's OK for
debug, I'd love to know your suggested alternative.
Do you leave such debugging code in your production code? If
not, no problem, but there's no point in making the << a
template. If so:

-- It doesn't work. Try it with std::vector<
std::vector< int , for example.

-- It very rapidly introduces undefined behavior, as you write
the above, and some other programmer provides the same
function, but with a comma as a separator.

For a quick debugging session, the simplest solution is to knock
out a non-template version in an unnamed namespace. For
anything else, you really need to define what is wanted; you
don't output raw vectors, but vectors with a semantic
signification, which determines how you format them. If you're
using vectors to represent both sets and sequences in a
mathematical context, for example, you'll doubtlessly have a
class for each, with the vector buried deep down in it. And
those classes will provide the formatted output.

If you find that you often need such debugging output (I don't,
but I'm sure that there are applications that to), then you
might want to come up with a general FormattedSequence class
template, with a template function to generate it (so you get
automatic type deduction); this could, of course, be in any
namespace you want.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 10 '08 #17

P: n/a
On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 7, 12:17 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& s, vector<A1, A2const& vec)
{
copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
return s;
}
}
Which has undefined behavior. You can only add template
specializations to namespace std when they depend on
user-defined types.
Formally true.
On practice it works just fine as long as One Definition Rule
is not violated.
Taking into account all of the code, including that which you
can't see or know about, such as in the implementation of the
library.

In other words, it works just fine as long as you're lucky.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 10 '08 #18

P: n/a
rio

"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org...
rio wrote:
>i know max(std::size_t) >= max(vector::size_type)

Could you provide a pointer into the standard to backup that claim? or are
you making a statement about a particular platform?
seems to me
should be
in the C standard in the definition of type size_t
>i know v.size()-1<=max(vector::size_type) <= max(std::size_t)

so size_t is ok


Best

Kai-Uwe Bux

Nov 10 '08 #19

P: n/a
On Nov 10, 10:22*am, James Kanze <james.ka...@gmail.comwrote:
On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 7, 12:17 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& s, vector<A1, A2const& vec)
* * * * {
* * * * * * copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
* * * * * * return s;
* * * * }
* * }
Which has undefined behavior. You can only add template
specializations to namespace std when they depend on
user-defined types.
Formally true.
On practice it works just fine as long as One Definition Rule
is not violated.

Taking into account all of the code, including that which you
can't see or know about, such as in the implementation of the
library.
Precisely.
In other words, it works just fine as long as you're lucky.
Not quite. Rather as long as one understands what he is doing.

--
Max
Nov 10 '08 #20

P: n/a
rio wrote:
"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org...
>rio wrote:
>>i know max(std::size_t) >= max(vector::size_type)
Could you provide a pointer into the standard to backup that claim? or are
you making a statement about a particular platform?

seems to me
should be
in the C standard in the definition of type size_t
I seriously doubt the C standard says anything about the
relation between 'std::size-t' and 'std::vector<T>::size_type'.
[...]
Schobi
Nov 10 '08 #21

P: n/a
rio wrote:
"Jeff Schwab" <je**@schwabcenter.comha scritto nel messaggio
news:Q7******************************@giganews.com ...
>Pete Becker wrote:
>>On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<ma***************@gmail.comsaid:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
if (!v.empty()) {
typedef std::ostream_iterator<Tout_iter;
copy(v.begin(), v.end() - 1, out_iter( out, " " ));
out << v.back();
why not write above only?
copy(v.begin(), v.end(), out_iter( out, " " ));
The "easy" solution outputs a trailing space.
is it not better the "operator<<" defined below?
....

No, it is not better.
the above seems ok what not seems ok to me that this
"
std::vector<int vettor1;

for(i=0; i<90; ++i)
vettor1[i]=i;
"
here goes in segmentation fault
is not vector1 self sizabile?
The vector is resizable, but does not resize itself on indexing. See
the push_back and resize methods.
than how you are sure that *all* the allocations have its deallocation?
for example it seems "std::vector<int>(ints,ints+4)"
copy in new memory the array ints[0..3]
and than it has to deallocate it but when and where
The vector's destructor deallocates the memory. Destruction can be a
wonderful thing. :)
Nov 10 '08 #22

P: n/a
James Kanze wrote:
On Nov 7, 7:21 pm, Jeff Schwab <j...@schwabcenter.comwrote:
>James Kanze wrote:
>>On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcenter.comwrote:
Pete Becker wrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
>>>><maxim.yegorush...@gmail.comsaid:
>>>>> namespace std {
> template<class A1, class A2>
> ostream& operator<<(ostream& s, vector<A1, A2const& vec)
>>>>Which has undefined behavior.
>>>The correct alternative, AIUI:
>>>template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
>>Correct in what sense?
>Correct in the sense that it implements the OP's intent, and
is allowed by the standard.
-- It doesn't work. Try it with std::vector<
std::vector< int , for example.
you don't output raw vectors, but vectors with a semantic
signification, which determines how you format them.
You're right. In real life, I don't write that sort of operator as a
template; I use a formatted_whatever type. Good call.

My original intent was to provide a Standard-compliant alternative to
specializing a template in std for non-UDT types. Pete pointed out the
previous poster's UB, but did not suggest any alternative. There is a
delicate art to keeping such abstract discussions both generic and
focused, especially on Usenet.
Nov 10 '08 #23

P: n/a
On Nov 10, 6:29*am, "rio" <a...@b.cwrote:
"rio" <a...@b.cha scritto nel
messaggionews:49***********************@reader5.ne ws.tin.it...
"Kai-Uwe Bux" <jkherci...@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org...
Juha Nieminen wrote:
>Jeff Schwab wrote:
template<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v){
* * if (!v.empty()) {
* * * * typedef std::ostream_iterator<Tout_iter;
* * * * 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<typename T>
std::ostream& operator<<(std::ostream& out, std::vector<Tconst& v) {
* * for(std::size_t i = 0; i < v.size()-1; ++i)
Nit: std::size_t is not guaranteed to be vector::size_type.
i know max(std::size_t) >= max(vector::size_type)
If this is true, then g++, VC++ and both of the library
implementations used with Sun CC are buggy, since they all allow
me to instantiate std::vector with an allocator which typedef's
size_type to unsigned long long.
i know *v.size()-1<=max(vector::size_type) <= max(std::size_t)
Given that v.size() returns a vector::size_type, it's safe to
say that v.size() <= max( vector::size_type ). But if
vector::size_type is an unsigned long long, and size_t is only
an unsigned long or an unsigned int, the second part is false.

Depending on what you're doing, it may be acceptable to suppose
that the default allocator is being used---I use size_t for this
a lot, when I know the actual instantiation of vector. But it's
not acceptable in a generic library.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 11 '08 #24

P: n/a
On Nov 10, 12:47*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 10, 10:22*am, James Kanze <james.ka...@gmail.comwrote:
On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 7, 12:17 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& s, vector<A1, A2const& vec)
* * * * {
* * * * * * copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
* * * * * * return s;
* * * * }
* * }
Which has undefined behavior. You can only add template
specializations to namespace std when they depend on
user-defined types.
Formally true.
On practice it works just fine as long as One Definition Rule
is not violated.
Taking into account all of the code, including that which
you can't see or know about, such as in the implementation
of the library.
Precisely.
In other words, it works just fine as long as you're lucky.
Not quite. Rather as long as one understands what he is doing.
And has access to, and has read and understood all of the source
code of the standard library he's using, and can guarantee that
his code will never be compiled using a compiler where this is
not the case.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 11 '08 #25

P: n/a
On Nov 11, 9:24*am, James Kanze <james.ka...@gmail.comwrote:
On Nov 10, 12:47*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 10, 10:22*am, James Kanze <james.ka...@gmail.comwrote:
On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 7, 12:17 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
<maxim.yegorush...@gmail.comsaid:
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<<(ostream& s, vector<A1, A2const& vec)
* * * * {
* * * * * * copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
"));
* * * * * * return s;
* * * * }
* * }
Which has undefined behavior. You can only add template
specializations to namespace std when they depend on
user-defined types.
Formally true.
On practice it works just fine as long as One Definition Rule
is not violated.
Taking into account all of the code, including that which
you can't see or know about, such as in the implementation
of the library.
Precisely.
In other words, it works just fine as long as you're lucky.
Not quite. Rather as long as one understands what he is doing.

And has access to, and has read and understood all of the source
code of the standard library he's using, and can guarantee that
his code will never be compiled using a compiler where this is
not the case.
You just confirmed that no luck involved here, this is just a question
of understanding. ;)

--
Max
Nov 11 '08 #26

P: n/a
Maxim Yegorushkin wrote:
On Nov 11, 9:24 am, James Kanze <james.ka...@gmail.comwrote:
>On Nov 10, 12:47 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.comwrote:
>>On Nov 10, 10:22 am, James Kanze <james.ka...@gmail.comwrote:
On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush...@gmail.comwrote:
On Nov 7, 12:17 pm, Pete Becker <p...@versatilecoding.comwrote:
>On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin <maxim.yegorush...@gmail.comsaid:
>>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<<(ostream& s, vector<A1, A2const& vec)
>> {
>> copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
>>"));
>> return s;
>> }
>> }
>Which has undefined behavior. [...]
In other words, it works just fine as long as you're lucky.
Not quite. Rather as long as one understands what he is doing.
And has access to, and has read and understood all of the source
code of the standard library he's using, and can guarantee that
his code will never be compiled using a compiler where this is
not the case.

You just confirmed that no luck involved here, this is just a question
of understanding. ;)
During the last decade, I had to write and maintain code
that was compiled using half a dozen different compilers
(and compiler versions), multiplied by several std lib
implementations (and versions thereof) multiplied by half
a dozen platforms multiplied by several different apps
the code was used for (standalone app/plugin, GUI/command
line...). There were enough different things we had to
have a thorough understanding of to make the idea of
having to have a thorough understanding of each of those
implementations and code versions rather unattractive.

Having followed this whole battle of words, I wonder what's
wrong with putting this operator into the global namespace
and altogether avoiding the hassle of having to know about
things you're not supposed to know about?
Max
Schobi
Nov 11 '08 #27

P: n/a
On Nov 11, 11:20*am, Hendrik Schober <spamt...@gmx.dewrote:

[]
* Having followed this whole battle of words, I wonder what's
* wrong with putting this operator into the global namespace
* and altogether avoiding the hassle of having to know about
* things you're not supposed to know about?
Nothing wrong and this is indeed the correct way to do so. I confused
this case with another one, sincere apologies.

--
Max
Nov 11 '08 #28

P: n/a
On Nov 11, 1:54*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 11, 11:20*am, Hendrik Schober <spamt...@gmx.dewrote:

[]
* Having followed this whole battle of words, I wonder what's
* wrong with putting this operator into the global namespace
* and altogether avoiding the hassle of having to know about
* things you're not supposed to know about?

Nothing wrong and this is indeed the correct way to do so. I confused
this case with another one, sincere apologies.
This what I was confusing it with:

#include <map>
#include <iostream>
#include <iterator>

// should be in namespace std::
template<class T, class U>
std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst&
p)
{
return s << p.first << ' ' << p.second;
}

int main()
{
typedef std::map<int, intMap;
Map m;
std::copy(
m.begin()
, m.end()
, std::ostream_iterator<Map::value_type>(std::cout)
);
}

It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.

--
Max
Nov 11 '08 #29

P: n/a
Maxim Yegorushkin wrote:
On Nov 11, 1:54 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
>On Nov 11, 11:20 am, Hendrik Schober <spamt...@gmx.dewrote:

[]
>> Having followed this whole battle of words, I wonder what's
wrong with putting this operator into the global namespace
and altogether avoiding the hassle of having to know about
things you're not supposed to know about?
Nothing wrong and this is indeed the correct way to do so. I confused
this case with another one, sincere apologies.

This what I was confusing it with:

#include <map>
#include <iostream>
#include <iterator>

// should be in namespace std::
template<class T, class U>
std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
{
return s << p.first << ' ' << p.second;
}

int main()
{
typedef std::map<int, intMap;
Map m;
std::copy(
m.begin()
, m.end()
, std::ostream_iterator<Map::value_type>(std::cout)
);
}

It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.
I would have asked the same question for this code. :)
I don't understand why it doesn't compile. It comes down
to this
ostr << val;
with 'ostr' being an 'std::basic_ostream<>' and 'val'
being an 'std::pair<>'. Why doesn't this find the global
operator?
Max
Schobi
Nov 11 '08 #30

P: n/a
On Nov 11, 2:40*pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
On Nov 11, 1:54 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 11, 11:20 am, Hendrik Schober <spamt...@gmx.dewrote:
[]
>* Having followed this whole battle of words, I wonder what's
* wrong with putting this operator into the global namespace
* and altogether avoiding the hassle of having to know about
* things you're not supposed to know about?
Nothing wrong and this is indeed the correct way to do so. I confused
this case with another one, sincere apologies.
This what I was confusing it with:
* * #include <map>
* * #include <iostream>
* * #include <iterator>
* * // should be in namespace std::
* * template<class T, class U>
* * std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
* * {
* * * * return s << p.first << ' ' << p.second;
* * }
* * int main()
* * {
* * * * typedef std::map<int, intMap;
* * * * Map m;
* * * * std::copy(
* * * * * * * m.begin()
* * * * * * , m.end()
* * * * * * , std::ostream_iterator<Map::value_type>(std::cout)
* * * * * * );
* * }
It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.

* I would have asked the same question for this code. :)
* I don't understand why it doesn't compile. It comes down
* to this
* * ostr << val;
* with 'ostr' being an 'std::basic_ostream<>' and 'val'
* being an 'std::pair<>'. Why doesn't this find the global
* operator?
Because expression "ostr << val" is template argument dependent and
thus is bound at the second phase of the two-phase name lookup. At the
second phase it uses ADL only to search for functions within
namespaces associated with ostr and val. ostr is std::basic_ostream
and val is std::pair<int, int>, thus one associated namespace is std.
int has no associated namespaces. So, the only namespace considered
for expression "ostr << val" is std, which lacks a suitable
operator<<().

--
Max
Nov 11 '08 #31

P: n/a
Maxim Yegorushkin wrote:
On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.dewrote:
>Maxim Yegorushkin wrote:
[...]
>> #include <map>
#include <iostream>
#include <iterator>
// should be in namespace std::
template<class T, class U>
std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
{
return s << p.first << ' ' << p.second;
}
int main()
{
typedef std::map<int, intMap;
Map m;
std::copy(
m.begin()
, m.end()
, std::ostream_iterator<Map::value_type>(std::cout)
);
}
It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.
I would have asked the same question for this code. :)
I don't understand why it doesn't compile. It comes down
to this
ostr << val;
with 'ostr' being an 'std::basic_ostream<>' and 'val'
being an 'std::pair<>'. Why doesn't this find the global
operator?

Because expression "ostr << val" is template argument dependent and
thus is bound at the second phase of the two-phase name lookup. At the
second phase it uses ADL only to search for functions within
namespaces associated with ostr and val. ostr is std::basic_ostream
and val is std::pair<int, int>, thus one associated namespace is std.
int has no associated namespaces. So, the only namespace considered
for expression "ostr << val" is std, which lacks a suitable
operator<<().
But lookup isn't ADL only. The enclosing namespaces are considered,
too, aren't they? And the global namespaces is always enclosing.
(I'm not saying you're wrong. I just don't understand this.)
Max
Schobi
Nov 11 '08 #32

P: n/a
On Nov 11, 3:36*pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
[...]
>* * #include <map>
* * #include <iostream>
* * #include <iterator>
* * // should be in namespace std::
* * template<class T, class U>
* * std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
* * {
* * * * return s << p.first << ' ' << p.second;
* * }
* * int main()
* * {
* * * * typedef std::map<int, intMap;
* * * * Map m;
* * * * std::copy(
* * * * * * * m.begin()
* * * * * * , m.end()
* * * * * * , std::ostream_iterator<Map::value_type>(std::cout)
* * * * * * );
* * }
It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.
* I would have asked the same question for this code. :)
* I don't understand why it doesn't compile. It comes down
* to this
* * ostr << val;
* with 'ostr' being an 'std::basic_ostream<>' and 'val'
* being an 'std::pair<>'. Why doesn't this find the global
* operator?
Because expression "ostr << val" is template argument dependent and
thus is bound at the second phase of the two-phase name lookup. At the
second phase it uses ADL only to search for functions within
namespaces associated with ostr and val. ostr is std::basic_ostream
and val is std::pair<int, int>, thus one associated namespace is std.
int has no associated namespaces. So, the only namespace considered
for expression "ostr << val" is std, which lacks a suitable
operator<<().

* But lookup isn't ADL only. The enclosing namespaces are considered,
* too, aren't they? And the global namespaces is always enclosing.
* (I'm not saying you're wrong. I just don't understand this.)
At the second stage of the two-phase name lookup (at the point of
template instantiation) it is ADL only.
* Schobi
--
Max

Nov 11 '08 #33

P: n/a
Maxim Yegorushkin wrote:
On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.dewrote:
>Maxim Yegorushkin wrote:
>>On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
[...]
#include <map>
#include <iostream>
#include <iterator>
// should be in namespace std::
template<class T, class U>
std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
{
return s << p.first << ' ' << p.second;
}
int main()
{
typedef std::map<int, intMap;
Map m;
std::copy(
m.begin()
, m.end()
, std::ostream_iterator<Map::value_type>(std::cout)
);
}
It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.
I would have asked the same question for this code. :)
I don't understand why it doesn't compile. It comes down
to this
ostr << val;
with 'ostr' being an 'std::basic_ostream<>' and 'val'
being an 'std::pair<>'. Why doesn't this find the global
operator?
Because expression "ostr << val" is template argument dependent and
thus is bound at the second phase of the two-phase name lookup. At the
second phase it uses ADL only to search for functions within
namespaces associated with ostr and val. ostr is std::basic_ostream
and val is std::pair<int, int>, thus one associated namespace is std.
int has no associated namespaces. So, the only namespace considered
for expression "ostr << val" is std, which lacks a suitable
operator<<().
But lookup isn't ADL only. The enclosing namespaces are considered,
too, aren't they? And the global namespaces is always enclosing.
(I'm not saying you're wrong. I just don't understand this.)

At the second stage of the two-phase name lookup (at the point of
template instantiation) it is ADL only.
I'm trying to come up with some trivial example that
illustrates this, but I fail. I have this

#include <iostream>

namespace N {
struct test { };

template< typename T >
void f(T) { std::cout << "f(T)\n"; }

void f(int) { std::cout << "f(int)\n"; }
}

template< typename T >
void g(T o) { f(o); }

int main()
{
N::test t;
g(t);
}

which compiles fine and gives the expected result.
What am I still missing.
Max
Schobi
Nov 11 '08 #34

P: n/a
On Nov 11, 4:39*pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.dewrote:
Maxim Yegorushkin wrote:
[...]
* * #include <map>
* * #include <iostream>
* * #include <iterator>
* * // should be in namespace std::
* * template<class T, class U>
* * std::ostream& operator<<(std::ostream& s, std::pair<T, Uconst& p)
* * {
* * * * return s << p.first << ' ' << p.second;
* * }
* * int main()
* * {
* * * * typedef std::map<int, intMap;
* * * * Map m;
* * * * std::copy(
* * * * * * * m.begin()
* * * * * * , m.end()
* * * * * * , std::ostream_iterator<Map::value_type>(std::cout)
* * * * * * );
* * }
It won't compile unless operator<<(std::ostream& s, std::pair<T, U>
const& p) is in namespace std.
* I would have asked the same question for this code. :)
* I don't understand why it doesn't compile. It comes down
* to this
* * ostr << val;
* with 'ostr' being an 'std::basic_ostream<>' and 'val'
* being an 'std::pair<>'. Why doesn't this find the global
* operator?
Because expression "ostr << val" is template argument dependent and
thus is bound at the second phase of the two-phase name lookup. At the
second phase it uses ADL only to search for functions within
namespaces associated with ostr and val. ostr is std::basic_ostream
and val is std::pair<int, int>, thus one associated namespace is std.
int has no associated namespaces. So, the only namespace considered
for expression "ostr << val" is std, which lacks a suitable
operator<<().
* But lookup isn't ADL only. The enclosing namespaces are considered,
* too, aren't they? And the global namespaces is always enclosing.
* (I'm not saying you're wrong. I just don't understand this.)
At the second stage of the two-phase name lookup (at the point of
template instantiation) it is ADL only.

* I'm trying to come up with some trivial example that
* illustrates this, but I fail. I have this

* * *#include <iostream>

* * *namespace N {
* * * * *struct test { };

* * * * *template< typename T >
* * * * *void f(T) { *std::cout << "f(T)\n"; }

* * * * *void f(int) { *std::cout << "f(int)\n"; }
* * *}

* * *template< typename T >
* * *void g(T o) { f(o); }

* * *int main()
* * *{
* * * * *N::test t;
* * * * *g(t);
* * *}

* which compiles fine and gives the expected result.
* What am I still missing.
Your example should work just fine.

Here is a simplified version of the problem with
std::ostream_iterator<std::pair< and a global
operator<<(std::ostream&, std::pair<>):

namespace N {

struct X {};

void bar(struct overload_for_compilers_with_no_two_phase_lookup&);

template<class Tvoid foo(T t) { bar(t); }

}

template<class Tvoid bar(T);

int main()
{
N::X x;
foo(x);
}

--
Max
Nov 11 '08 #35

P: n/a
rio
"Hendrik Schober" <sp******@gmx.deha scritto nel messaggio
news:gf**********@hoshi.visyn.net...
rio wrote:
>"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org.. .
>>rio wrote:
i know max(std::size_t) >= max(vector::size_type)
Could you provide a pointer into the standard to backup that claim? or are
you making a statement about a particular platform?

seems to me
should be
in the C standard in the definition of type size_t

I seriously doubt the C standard says anything about the
relation between 'std::size-t' and 'std::vector<T>::size_type'.
ok
what about relation between "size_t"
and 'std::vector<T>::size_type'?
>[...]

Schobi

Nov 13 '08 #36

P: n/a
rio

"Jeff Schwab" <je**@schwabcenter.comha scritto nel messaggio
news:2s******************************@giganews.com ...
rio wrote:
The vector's destructor deallocates the memory. Destruction can be a
wonderful thing. :)
yes i know it, but it is better to know where it is done

Nov 13 '08 #37

P: n/a
rio wrote:
"Hendrik Schober" <sp******@gmx.deha scritto nel messaggio
news:gf**********@hoshi.visyn.net...
>rio wrote:
>>"Kai-Uwe Bux" <jk********@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org. ..
rio wrote:
i know max(std::size_t) >= max(vector::size_type)
Could you provide a pointer into the standard to backup that claim? or
are you making a statement about a particular platform?

seems to me
should be
in the C standard in the definition of type size_t

I seriously doubt the C standard says anything about the
relation between 'std::size-t' and 'std::vector<T>::size_type'.

ok
what about relation between "size_t"
and 'std::vector<T>::size_type'?
It's not dealt with anywhere. As far as I know, all we know about
std::size_t is that it is unsigned and the return type of the sizeof()
operator. Whether it can hold any value that std::vector<T>::size_type can
hold, I have not seen in the standard (neither the C standard, which says
nothing about vector<T>::size_type nor the C++ standard).
Best

Kai-Uwe Bux
Nov 13 '08 #38

P: n/a
rio wrote:
"Jeff Schwab" <je**@schwabcenter.comha scritto nel messaggio
news:2s******************************@giganews.com ...
>rio wrote:
The vector's destructor deallocates the memory. Destruction can be a
wonderful thing. :)

yes i know it, but it is better to know where it is done
C++ destruction is deterministic, well-defined, and fairly easy to
understand. The fact that something is taken care of by a destructor
doesn't mean you don't know where it's done. If you use automatic
allocation, destruction happens when the object goes out of scope.
Nov 13 '08 #39

P: n/a
On Nov 13, 6:58*pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
rio wrote:
"Hendrik Schober" <spamt...@gmx.deha scritto nel messaggio
news:gf**********@hoshi.visyn.net...
rio wrote:
"Kai-Uwe Bux" <jkherci...@gmx.netha scritto nel messaggio
news:49***********************@read.cnntp.org. ..
rio wrote:
i know max(std::size_t) >= max(vector::size_type)
Could you provide a pointer into the standard to backup
that claim? or are you making a statement about a
particular platform?
>seems to me should be in the C standard in the definition
of type size_t
*I seriously doubt the C standard says anything about the
*relation between 'std::size-t' and
'std::vector<T>::size_type'.
ok
what about relation between "size_t"
and 'std::vector<T>::size_type'?
It's not dealt with anywhere. As far as I know, all we know
about std::size_t is that it is unsigned and the return type
of the sizeof() operator. Whether it can hold any value that
std::vector<T>::size_type can hold, I have not seen in the
standard (neither the C standard, which says nothing about
vector<T>::size_type nor the C++ standard).
Well, vector<T>::size_type has to be an unsigned integral type,
capable of representing all of the positive values of
vector<T>::difference_type. And vector<T>::difference_type must
be the type returned by subtracting two iterators,

I'm almost sure that the intent was that vector<T>::size_type
should be then same as the size_type of it's allocator; this is,
at least, what all of the implementations I know do. Which
means that it can be pretty much anything the user wants (as
long as it is an unsigned integral type); the default allocator
is required to typedef it to size_t. (The current standard
states that it should be "a type that can represent the size of
the largest object in the allocation model." This is certainly
wrong, since it is incompatible with the requirement that it
must contain all of the positive values which the
difference_type can contain---I've used systems where the
largest single object was 65365, but where pointers were
effectively 20 bits, and the difference between two pointers
could be 1 MB.) All of this has been rewritten in the current
draft to be expressed in terms of concepts, so someone has a lot
of detailed reading to do between here and Jan. 15th (when I
have to submit my comments on the CD to AFNOR).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 13 '08 #40

P: n/a
James Kanze wrote:
I'm almost sure that the intent was that vector<T>::size_type
should be then same as the size_type of it's allocator; this is,
at least, what all of the implementations I know do. Which
means that it can be pretty much anything the user wants (as
long as it is an unsigned integral type);
I don't think that's true.
the default allocator is required to typedef it to size_t.
It's not just that the default allocator has to use size_t. The standard
containers are always permitted to assume that
SomeAllocator<T>::size_type is size_t, even if SomeAllocator is
user-supplied. See 20.1.5, bullet 4.
Nov 13 '08 #41

P: n/a
On Nov 13, 11:15 pm, Jeff Schwab <j...@schwabcenter.comwrote:
James Kanze wrote:
I'm almost sure that the intent was that
vector<T>::size_type should be then same as the size_type of
it's allocator; this is, at least, what all of the
implementations I know do. Which means that it can be
pretty much anything the user wants (as long as it is an
unsigned integral type);
I don't think that's true.
What isn't true, that the intent was that it should be the same
as size_type of the allocator, or that that's what most
implementations do. With regards to the implementations, there
does seem to be some differences: g++ and the STLPort use
size_t, but Dinkumware and Roguewave use allocator::size_type.
With regards to the "intent", it's very difficult to know what
the intent was behind anything to do with allocators, but if
there was no intent that the user could customize it, why the
typedef to begin with.
the default allocator is required to typedef it to size_t.
It's not just that the default allocator has to use size_t.
The standard containers are always permitted to assume that
SomeAllocator<T>::size_type is size_t, even if SomeAllocator
is user-supplied. See 20.1.5, bullet 4.
You mean paragraph 4. Then see paragraph 5. The whole thing is
a farce, of course---the standard says that it doesn't require
user supplied allocators to be useful for anything, then goes on
to say that the implementation is "encouraged" to make them
useful. At the time of standardization, there was considerable
discussion about allocators---a lot of people seemed to want
them, but for a lot a of different reasons. I can remember
hearing at least two justifications for this additional
complexity: to support different pointer sizes (i.e. far
pointers on an Intel at the time), and to support things like
putting containers in shared memory. A mimimum implementation
of the standard, i.e. one which takes full advantage of the
freedoms in 20.1.5/4, doesn't support either. Quality
implementations, such as Dinkumware, do take the statement of
intent in paragraph 5 seriously, however. (Whether this means
that you actually can use allocators to put a container in
shared memory, I really don't know. If not, however, then
allocators are just excess baggage.)

Anyway, with regards to my original statement: it should be
ammended to say that it's implementation defined whether
vector<T>::size_type can be anything the user wants, but the
standard explicitely "encourages" an implementation to support
this possibility.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 14 '08 #42

P: n/a
Maxim Yegorushkin wrote:
On Nov 11, 4:39 pm, Hendrik Schober <spamt...@gmx.dewrote:
>Maxim Yegorushkin wrote:
>>On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.dewrote:
[...]
>>> But lookup isn't ADL only. The enclosing namespaces are considered,
too, aren't they? And the global namespaces is always enclosing.
(I'm not saying you're wrong. I just don't understand this.)
At the second stage of the two-phase name lookup (at the point of
template instantiation) it is ADL only.
I'm trying to come up with some trivial example that
illustrates this, but I fail. [...]

Here is a simplified version of the problem with
std::ostream_iterator<std::pair< and a global
operator<<(std::ostream&, std::pair<>):

namespace N {

struct X {};

void bar(struct overload_for_compilers_with_no_two_phase_lookup&);

template<class Tvoid foo(T t) { bar(t); }

}

template<class Tvoid bar(T);

int main()
{
N::X x;
foo(x);
}
Thanks, I didn't know this.
I suppose the rationale is to limit the number of possibly
surprising overloads considered?
Max
Schobi
Nov 18 '08 #43

This discussion thread is closed

Replies have been disabled for this discussion.