cout << vector<string>

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • barcaroller

    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?





  • Maxim Yegorushkin

    #2
    Re: cout &lt;&lt; vector&lt;strin g&gt;

    On Nov 6, 11:06 pm, "barcarolle r" <barcarol...@mu sic.netwrote:
    In the boost::program_ options tutorial, the author included the following
    code:
    >
        cout << "Input files are: "
             << vm["input-file"].as< vector<string()
             << "\n";
    >
    Basically, he is trying to print a vector of string, in one line.  I could
    not get this compile (let alone run).  To get it to compile and run, I had
    to re-write it as:
    >
        vector<stringv = vm["input-file"].as< vector<string() ;
    >
        vector<string>: :const_iterator i;
    >
        for (   i  = v.begin();
                i != v.end();
              ++i )
        {
            cout << *citer << " ";
        }
    >
    Does anyone know if the original line of code is correct?  If so, what was I
    missing?
    The example probably assumes there is an overloaded operator<<() for
    std::ostream and std::vector<>, something like this:

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

    namespace std {

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

    }

    --
    Max

    Comment

    • Pete Becker

      #3
      Re: cout &lt;&lt; vector&lt;strin g&gt;

      On 2008-11-06 18:06:47 -0500, "barcarolle r" <barcaroller@mu sic.netsaid:
      >
      In the boost::program_ options tutorial, the author included the following
      code:
      >
      >
      cout << "Input files are: "
      << vm["input-file"].as< vector<string()
      << "\n";
      >
      >
      >
      Does anyone know if the original line of code is correct?
      Not in standard C++.
      If so, what was I
      missing?
      Either some code that was mentioned somewhere in the tutorial, or a
      better tutorial.

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

      Comment

      • Pete Becker

        #4
        Re: cout &lt;&lt; vector&lt;strin g&gt;

        On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
        <maxim.yegorush kin@gmail.comsa id:
        >
        The example probably assumes there is an overloaded operator<<() for
        std::ostream and std::vector<>, something like this:
        >
        #include <ostream>
        #include <iterator>
        #include <algorithm>
        >
        namespace std {
        >
        template<class A1, class A2>
        ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
        {
        copy(vec.begin( ), vec.end(), ostream_iterato r<A1>(s, "
        "));
        return s;
        }
        >
        }
        Which has undefined behavior. You can only add template specializations
        to namespace std when they depend on user-defined types.

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

        Comment

        • Jeff Schwab

          #5
          Re: cout &lt;&lt; vector&lt;strin g&gt;

          Pete Becker wrote:
          On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
          <maxim.yegorush kin@gmail.comsa id:
          >The example probably assumes there is an overloaded operator<<() for
          >std::ostream and std::vector<>, something like this:
          > namespace std {
          >>
          > template<class A1, class A2>
          > ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
          Which has undefined behavior. You can only add template specializations
          to namespace std when they depend on user-defined types.
          The correct alternative, AIUI:

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

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

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

          Comment

          • Juha Nieminen

            #6
            Re: cout &lt;&lt; vector&lt;strin g&gt;

            Jeff Schwab wrote:
            template<typena me T>
            std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
            if (!v.empty()) {
            typedef std::ostream_it erator<Tout_ite r;
            copy(v.begin(), v.end() - 1, out_iter( out, " " ));
            out << v.back();
            }
            return out;
            }
            Is there some advantage of that code over a shorter and simpler:

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

            Comment

            • Kai-Uwe Bux

              #7
              Re: cout &lt;&lt; vector&lt;strin g&gt;

              Juha Nieminen wrote:
              Jeff Schwab wrote:
              >template<typen ame T>
              >std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
              > if (!v.empty()) {
              > typedef std::ostream_it erator<Tout_ite r;
              > copy(v.begin(), v.end() - 1, out_iter( out, " " ));
              > out << v.back();
              > }
              > return out;
              >}
              >
              Is there some advantage of that code over a shorter and simpler:
              >
              template<typena me T>
              std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
              for(std::size_t i = 0; i < v.size()-1; ++i)
              Nit: std::size_t is not guaranteed to be vector::size_ty pe.
              out << v[i] << " ";
              out << v.back();
              I think, v.back() has undefined behavior if the v is empty.
              return out;
              }

              Best

              Kai-Uwe Bux

              Comment

              • Jeff Schwab

                #8
                Re: cout &lt;&lt; vector&lt;strin g&gt;

                Juha Nieminen wrote:
                Jeff Schwab wrote:
                >template<typen ame T>
                >std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                > if (!v.empty()) {
                > typedef std::ostream_it erator<Tout_ite r;
                > copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                > out << v.back();
                > }
                > return out;
                >}
                >
                Is there some advantage of that code over a shorter and simpler:
                >
                template<typena me T>
                std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                for(std::size_t i = 0; i < v.size()-1; ++i)
                out << v[i] << " ";
                out << v.back();
                return out;
                }
                The use of the standard algorithm (rather than a hand-rolled loop) helps
                separate the different levels of abstraction. In your example, the code
                that works with an individual datum of type T is all mixed up with the
                code that works with the vector as a whole. There are decent
                discussions of this in Effective STL (Scott Meyers) and Clean Code
                (Robert Martin).

                Comment

                • James Kanze

                  #9
                  Re: cout &lt;&lt; vector&lt;strin g&gt;

                  On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
                  Pete Becker wrote:
                  On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
                  <maxim.yegorush ...@gmail.comsa id:
                  The example probably assumes there is an overloaded operator<<() for
                  std::ostream and std::vector<>, something like this:
                  namespace std {
                  >
                  template<class A1, class A2>
                  ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
                  Which has undefined behavior. You can only add template specializations
                  to namespace std when they depend on user-defined types.
                  The correct alternative, AIUI:
                  #include <algorithm>
                  #include <iostream>
                  #include <iterator>
                  #include <vector>
                  template<typena me T>
                  std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                  if (!v.empty()) {
                  typedef std::ostream_it erator<Tout_ite r;
                  copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                  out << v.back();
                  }
                  return out;
                  }
                  int main() {
                  int const ints[] = { 1, 2, 3, 4 };
                  std::cout << std::vector<int >( ints, ints + 4 ) << '\n';
                  }
                  Correct in what sense? It's OK for simple test, like this, but
                  it's certainly not something you'd allow in production code.

                  --
                  James Kanze (GABI Software) email:james.kan ze@gmail.com
                  Conseils en informatique orientée objet/
                  Beratung in objektorientier ter Datenverarbeitu ng
                  9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                  Comment

                  • Jeff Schwab

                    #10
                    Re: cout &lt;&lt; vector&lt;strin g&gt;

                    Jeff Schwab wrote:
                    Juha Nieminen wrote:
                    >Jeff Schwab wrote:
                    >>template<type name T>
                    >>std::ostrea m& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                    >> if (!v.empty()) {
                    >> typedef std::ostream_it erator<Tout_ite r;
                    >> copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                    >> out << v.back();
                    >> }
                    >> return out;
                    >>}
                    >>
                    > Is there some advantage of that code over a shorter and simpler:
                    >>
                    >template<typen ame T>
                    >std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                    > for(std::size_t i = 0; i < v.size()-1; ++i)
                    > out << v[i] << " ";
                    > out << v.back();
                    > return out;
                    >}
                    >
                    The use of the standard algorithm (rather than a hand-rolled loop) helps
                    separate the different levels of abstraction. In your example, the code
                    that works with an individual datum of type T is all mixed up with the
                    code that works with the vector as a whole. There are decent
                    discussions of this in Effective STL (Scott Meyers) and Clean Code
                    (Robert Martin).
                    You know, the code I posted has exactly the same problem I pointed out
                    in yours: the level of abstraction is mixed. I was imagining the work
                    split neatly between two standard utilities:

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

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

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

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

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

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

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

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

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

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

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

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


                    The output operator for the vector still has two responsibilitie s:
                    Configuration/composition of the utilities to perform the actual output,
                    and implementation of the standard conventions for operator<<, e.g.
                    returning the output stream by reference. It probably should be further
                    refactored along those lines:

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

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

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

                    out_iterator( out, separator<T>::v alue );

                    Comment

                    • Jeff Schwab

                      #11
                      Re: cout &lt;&lt; vector&lt;strin g&gt;

                      James Kanze wrote:
                      On Nov 7, 1:32 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
                      >Pete Becker wrote:
                      >>On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
                      >><maxim.yegoru sh...@gmail.com said:
                      >>>The example probably assumes there is an overloaded operator<<() for
                      >>>std::ostre am and std::vector<>, something like this:
                      >>> namespace std {
                      >>> template<class A1, class A2>
                      >>> ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
                      >>Which has undefined behavior. You can only add template specializations
                      >>to namespace std when they depend on user-defined types.
                      >
                      >The correct alternative, AIUI:
                      >
                      >#include <algorithm>
                      >#include <iostream>
                      >#include <iterator>
                      >#include <vector>
                      >
                      >template<typen ame T>
                      >std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                      > if (!v.empty()) {
                      > typedef std::ostream_it erator<Tout_ite r;
                      > copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                      > out << v.back();
                      > }
                      > return out;
                      >}
                      >
                      >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.

                      Comment

                      • rio

                        #12
                        Re: cout &lt;&lt; vector&lt;strin g&gt;


                        "Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
                        news:49144af2$0 $17068$6e1ede2f @read.cnntp.org ...
                        Juha Nieminen wrote:
                        >
                        >Jeff Schwab wrote:
                        >>template<type name T>
                        >>std::ostrea m& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                        >> if (!v.empty()) {
                        >> typedef std::ostream_it erator<Tout_ite r;
                        >> copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                        >> out << v.back();
                        >> }
                        >> return out;
                        >>}
                        >>
                        > Is there some advantage of that code over a shorter and simpler:
                        >>
                        >template<typen ame T>
                        >std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                        > for(std::size_t i = 0; i < v.size()-1; ++i)
                        >
                        Nit: std::size_t is not guaranteed to be vector::size_ty pe.
                        so could be
                        std::size_t != vector::size_ty pe
                        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


                        Comment

                        • rio

                          #13
                          Re: cout &lt;&lt; vector&lt;strin g&gt;


                          "Jeff Schwab" <jeff@schwabcen ter.comha scritto nel messaggio
                          news:Q72dnf5yWq jvqInUnZ2dnUVZ_ vCdnZ2d@giganew s.com...
                          Pete Becker wrote:
                          >On 2008-11-07 06:03:15 -0500, Maxim Yegorushkin
                          ><maxim.yegorus hkin@gmail.coms aid:
                          #include <algorithm>
                          #include <iostream>
                          #include <iterator>
                          #include <vector>
                          >
                          template<typena me T>
                          std::ostream& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                          if (!v.empty()) {
                          typedef std::ostream_it erator<Tout_ite r;
                          copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                          out << v.back();
                          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<typena me T>
                          std::ostream& operator<<(std: :ostream& out, std::vector<T>c onst& 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<in t>(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';
                          }


                          Comment

                          • rio

                            #14
                            Re: cout &lt;&lt; vector&lt;strin g&gt;


                            "rio" <a@b.cha scritto nel messaggio
                            news:4916aba2$0 $40315$4fafbaef @reader5.news.t in.it...
                            >
                            "Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
                            news:49144af2$0 $17068$6e1ede2f @read.cnntp.org ...
                            >Juha Nieminen wrote:
                            >>
                            >>Jeff Schwab wrote:
                            >>>template<typ ename T>
                            >>>std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                            >>> if (!v.empty()) {
                            >>> typedef std::ostream_it erator<Tout_ite r;
                            >>> copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                            >>> out << v.back();
                            >>> }
                            >>> return out;
                            >>>}
                            >>>
                            >> Is there some advantage of that code over a shorter and simpler:
                            >>>
                            >>template<type name T>
                            >>std::ostrea m& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                            >> for(std::size_t i = 0; i < v.size()-1; ++i)
                            >>
                            >Nit: std::size_t is not guaranteed to be vector::size_ty pe.
                            i know max(std::size_t ) >= max(vector::siz e_type)
                            i know v.size()-1<=max(vector:: size_type) <= max(std::size_t )

                            so size_t is ok



                            Comment

                            • Kai-Uwe Bux

                              #15
                              Re: cout &lt;&lt; vector&lt;strin g&gt;

                              rio wrote:
                              >
                              "rio" <a@b.cha scritto nel messaggio
                              news:4916aba2$0 $40315$4fafbaef @reader5.news.t in.it...
                              >>
                              >"Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
                              >news:49144af2$ 0$17068$6e1ede2 f@read.cnntp.or g...
                              >>Juha Nieminen wrote:
                              >>>
                              >>>Jeff Schwab wrote:
                              >>>>template<ty pename T>
                              >>>>std::ostrea m& operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                              >>>> if (!v.empty()) {
                              >>>> typedef std::ostream_it erator<Tout_ite r;
                              >>>> copy(v.begin(), v.end() - 1, out_iter( out, " " ));
                              >>>> out << v.back();
                              >>>> }
                              >>>> return out;
                              >>>>}
                              >>>>
                              >>> Is there some advantage of that code over a shorter and simpler:
                              >>>>
                              >>>template<typ ename T>
                              >>>std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& v) {
                              >>> for(std::size_t i = 0; i < v.size()-1; ++i)
                              >>>
                              >>Nit: std::size_t is not guaranteed to be vector::size_ty pe.
                              >
                              i know max(std::size_t ) >= max(vector::siz e_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

                              Comment

                              Working...