473,513 Members | 2,560 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 4468
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2616
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
7337
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
7270
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
7397
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. ...
0
7565
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...
1
7128
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...
0
5704
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
4759
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...
0
3255
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...
1
817
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
473
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.