cout << vector<string>

Discussion in 'C++' started by barcaroller, Nov 6, 2008.

  1. barcaroller

    barcaroller Guest

    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<string> v = 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?
    barcaroller, Nov 6, 2008
    #1
    1. Advertising

  2. Re: cout << vector<string>

    On Nov 6, 11:06 pm, "barcaroller" <> wrote:
    > 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<string> v = 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::eek:stream 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, A2> const& vec)
    {
    copy(vec.begin(), vec.end(), ostream_iterator<A1>(s, "
    "));
    return s;
    }

    }

    --
    Max
    Maxim Yegorushkin, Nov 7, 2008
    #2
    1. Advertising

  3. Re: cout << vector<string>

    Jeff Schwab wrote:
    > template<typename T>
    > std::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    > if (!v.empty()) {
    > typedef std::eek:stream_iterator<T> out_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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    for(std::size_t i = 0; i < v.size()-1; ++i)
    out << v << " ";
    out << v.back();
    return out;
    }
    Juha Nieminen, Nov 7, 2008
    #3
  4. barcaroller

    Kai-Uwe Bux Guest

    Re: cout << vector<string>

    Juha Nieminen wrote:

    > Jeff Schwab wrote:
    >> template<typename T>
    >> std::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    >> if (!v.empty()) {
    >> typedef std::eek:stream_iterator<T> out_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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& 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 << " ";
    > out << v.back();


    I think, v.back() has undefined behavior if the v is empty.

    > return out;
    > }



    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Nov 7, 2008
    #4
  5. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 7, 1:32 pm, Jeff Schwab <> wrote:
    > Pete Becker wrote:
    > > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > > <> said:
    > >> The example probably assumes there is an overloaded operator<<() for
    > >> std::eek:stream and std::vector<>, something like this:
    > >> namespace std {

    >
    > >> template<class A1, class A2>
    > >> ostream& operator<<(ostream& s, vector<A1, A2> const& 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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    > if (!v.empty()) {
    > typedef std::eek:stream_iterator<T> out_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:
    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
    James Kanze, Nov 7, 2008
    #5
  6. barcaroller

    Kai-Uwe Bux Guest

    Re: cout << vector<string>

    rio wrote:

    >
    > "rio" <> ha scritto nel messaggio
    > news:4916aba2$0$40315$...
    >>
    >> "Kai-Uwe Bux" <> ha scritto nel messaggio
    >> news:49144af2$0$17068$...
    >>> Juha Nieminen wrote:
    >>>
    >>>> Jeff Schwab wrote:
    >>>>> template<typename T>
    >>>>> std::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    >>>>> if (!v.empty()) {
    >>>>> typedef std::eek:stream_iterator<T> out_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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& 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
    Kai-Uwe Bux, Nov 10, 2008
    #6
  7. Re: cout << vector<string>

    On Nov 7, 12:17 pm, Pete Becker <> wrote:
    > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > <> said:
    >
    >
    >
    >
    >
    > > The example probably assumes there is an overloaded operator<<() for
    > > std::eek:stream 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, A2> const& 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
    Maxim Yegorushkin, Nov 10, 2008
    #7
  8. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 7, 7:21 pm, Jeff Schwab <> wrote:
    > James Kanze wrote:
    > > On Nov 7, 1:32 pm, Jeff Schwab <> wrote:
    > >> Pete Becker wrote:
    > >>> On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > >>> <> said:
    > >>>> The example probably assumes there is an overloaded operator<<() for
    > >>>> std::eek:stream and std::vector<>, something like this:
    > >>>> namespace std {
    > >>>> template<class A1, class A2>
    > >>>> ostream& operator<<(ostream& s, vector<A1, A2> const& 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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    > >> if (!v.empty()) {
    > >> typedef std::eek:stream_iterator<T> out_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:
    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
    James Kanze, Nov 10, 2008
    #8
  9. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 10, 10:19 am, Maxim Yegorushkin <>
    wrote:
    > On Nov 7, 12:17 pm, Pete Becker <> wrote:
    > > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > > <> said:


    > > > The example probably assumes there is an overloaded
    > > > operator<<() for std::eek:stream 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, A2> const& 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:
    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
    James Kanze, Nov 10, 2008
    #9
  10. Re: cout << vector<string>

    On Nov 10, 10:22 am, James Kanze <> wrote:
    > On Nov 10, 10:19 am, Maxim Yegorushkin <>
    > wrote:
    >
    >
    >
    > > On Nov 7, 12:17 pm, Pete Becker <> wrote:
    > > > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > > > <> said:
    > > > > The example probably assumes there is an overloaded
    > > > > operator<<() for std::eek:stream 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, A2> const& 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
    Maxim Yegorushkin, Nov 10, 2008
    #10
  11. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 10, 6:29 am, "rio" <> wrote:
    > "rio" <> ha scritto nel
    > messaggionews:4916aba2$0$40315$...
    > > "Kai-Uwe Bux" <> ha scritto nel messaggio
    > >news:49144af2$0$17068$...
    > >> Juha Nieminen wrote:


    > >>> Jeff Schwab wrote:
    > >>>> template<typename T>
    > >>>> std::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& v) {
    > >>>>     if (!v.empty()) {
    > >>>>         typedef std::eek:stream_iterator<T> out_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::eek:stream& operator<<(std::eek:stream& out, std::vector<T> const& 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:
    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
    James Kanze, Nov 11, 2008
    #11
  12. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 10, 12:47 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 10, 10:22 am, James Kanze <> wrote:
    > > On Nov 10, 10:19 am, Maxim Yegorushkin <>
    > > wrote:


    > > > On Nov 7, 12:17 pm, Pete Becker <> wrote:
    > > > > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > > > > <> said:
    > > > > > The example probably assumes there is an overloaded
    > > > > > operator<<() for std::eek:stream 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, A2> const& 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:
    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
    James Kanze, Nov 11, 2008
    #12
  13. Re: cout << vector<string>

    On Nov 11, 9:24 am, James Kanze <> wrote:
    > On Nov 10, 12:47 pm, Maxim Yegorushkin <>
    > wrote:
    >
    >
    >
    > > On Nov 10, 10:22 am, James Kanze <> wrote:
    > > > On Nov 10, 10:19 am, Maxim Yegorushkin <>
    > > > wrote:
    > > > > On Nov 7, 12:17 pm, Pete Becker <> wrote:
    > > > > > On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
    > > > > > <> said:
    > > > > > > The example probably assumes there is an overloaded
    > > > > > > operator<<() for std::eek:stream 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, A2> const& 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
    Maxim Yegorushkin, Nov 11, 2008
    #13
  14. Re: cout << vector<string>

    On Nov 11, 11:20 am, Hendrik Schober <> wrote:

    []

    >   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
    Maxim Yegorushkin, Nov 11, 2008
    #14
  15. Re: cout << vector<string>

    On Nov 11, 1:54 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 11, 11:20 am, Hendrik Schober <> wrote:
    >
    > []
    >
    > >   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::eek:stream& operator<<(std::eek:stream& s, std::pair<T, U> const&
    p)
    {
    return s << p.first << ' ' << p.second;
    }

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

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

    --
    Max
    Maxim Yegorushkin, Nov 11, 2008
    #15
  16. Re: cout << vector<string>

    On Nov 11, 2:40 pm, Hendrik Schober <> wrote:
    > Maxim Yegorushkin wrote:
    > > On Nov 11, 1:54 pm, Maxim Yegorushkin <>
    > > wrote:
    > >> On Nov 11, 11:20 am, Hendrik Schober <> wrote:

    >
    > >> []

    >
    > >>>   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::eek:stream& operator<<(std::eek:stream& s, std::pair<T, U> const& p)
    > >     {
    > >         return s << p.first << ' ' << p.second;
    > >     }

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

    >
    > > It won't compile unless operator<<(std::eek:stream& 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
    Maxim Yegorushkin, Nov 11, 2008
    #16
  17. Re: cout << vector<string>

    On Nov 11, 3:36 pm, Hendrik Schober <> wrote:
    > Maxim Yegorushkin wrote:
    > > On Nov 11, 2:40 pm, Hendrik Schober <> wrote:
    > >> Maxim Yegorushkin wrote:

    > > [...]
    > >>>     #include <map>
    > >>>     #include <iostream>
    > >>>     #include <iterator>
    > >>>     // should be in namespace std::
    > >>>     template<class T, class U>
    > >>>     std::eek:stream& operator<<(std::eek:stream& s, std::pair<T, U> const& p)
    > >>>     {
    > >>>         return s << p.first << ' ' << p.second;
    > >>>     }
    > >>>     int main()
    > >>>     {
    > >>>         typedef std::map<int, int> Map;
    > >>>         Map m;
    > >>>         std::copy(
    > >>>               m.begin()
    > >>>             , m.end()
    > >>>             , std::eek:stream_iterator<Map::value_type>(std::cout)
    > >>>             );
    > >>>     }
    > >>> It won't compile unless operator<<(std::eek:stream& 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
    Maxim Yegorushkin, Nov 11, 2008
    #17
  18. Re: cout << vector<string>

    On Nov 11, 4:39 pm, Hendrik Schober <> wrote:
    > Maxim Yegorushkin wrote:
    > > On Nov 11, 3:36 pm, Hendrik Schober <> wrote:
    > >> Maxim Yegorushkin wrote:
    > >>> On Nov 11, 2:40 pm, Hendrik Schober <> wrote:
    > >>>> Maxim Yegorushkin wrote:
    > >>> [...]
    > >>>>>     #include <map>
    > >>>>>     #include <iostream>
    > >>>>>     #include <iterator>
    > >>>>>     // should be in namespace std::
    > >>>>>     template<class T, class U>
    > >>>>>     std::eek:stream& operator<<(std::eek:stream& s, std::pair<T, U> const& p)
    > >>>>>     {
    > >>>>>         return s << p.first << ' ' << p.second;
    > >>>>>     }
    > >>>>>     int main()
    > >>>>>     {
    > >>>>>         typedef std::map<int, int> Map;
    > >>>>>         Map m;
    > >>>>>         std::copy(
    > >>>>>               m.begin()
    > >>>>>             , m.end()
    > >>>>>             , std::eek:stream_iterator<Map::value_type>(std::cout)
    > >>>>>             );
    > >>>>>     }
    > >>>>> It won't compile unless operator<<(std::eek:stream& 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::eek:stream_iterator<std::pair<> > and a global
    operator<<(std::eek:stream&, std::pair<>):

    namespace N {

    struct X {};

    void bar(struct overload_for_compilers_with_no_two_phase_lookup&);

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

    }

    template<class T> void bar(T);

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

    --
    Max
    Maxim Yegorushkin, Nov 11, 2008
    #18
  19. barcaroller

    Kai-Uwe Bux Guest

    Re: cout << vector<string>

    rio wrote:

    > "Hendrik Schober" <> ha scritto nel messaggio
    > news:gf972o$csj$...
    >> rio wrote:
    >>> "Kai-Uwe Bux" <> ha scritto nel messaggio
    >>> news:4917cc4e$0$17068$...
    >>>> 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
    Kai-Uwe Bux, Nov 13, 2008
    #19
  20. barcaroller

    James Kanze Guest

    Re: cout << vector<string>

    On Nov 13, 6:58 pm, Kai-Uwe Bux <> wrote:
    > rio wrote:
    > > "Hendrik Schober" <> ha scritto nel messaggio
    > >news:gf972o$csj$...
    > >> rio wrote:
    > >>> "Kai-Uwe Bux" <> ha scritto nel messaggio
    > >>>news:4917cc4e$0$17068$...
    > >>>> 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:
    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
    James Kanze, Nov 13, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. abi

    man cout or info cout

    abi, Jun 27, 2003, in forum: C++
    Replies:
    2
    Views:
    1,647
  2. Pmb

    std::cout vs cout

    Pmb, Jun 2, 2004, in forum: C++
    Replies:
    2
    Views:
    4,404
    Leor Zolman
    Jun 2, 2004
  3. Replies:
    4
    Views:
    316
    Howard
    Sep 15, 2005
  4. Replies:
    8
    Views:
    1,910
    Csaba
    Feb 18, 2006
  5. Stefan Ram

    Re: cout vs std::cout

    Stefan Ram, Sep 28, 2008, in forum: C++
    Replies:
    7
    Views:
    475
Loading...

Share This Page