cout << vector<string>

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

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

    On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
    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:
    >
        #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.
    Formally true.

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

    --
    Max

    Comment

    • James Kanze

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

      On Nov 7, 7:21 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
      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.yegorus h...@gmail.coms aid:
      >>The example probably assumes there is an overloaded operator<<() for
      >>std::ostrea m 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
      >specialization s 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.
      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 FormattedSequen ce 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: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

      • James Kanze

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

        On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
        wrote:
        On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
        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:
        #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.
        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: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

        • rio

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


          "Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
          news:4917cc4e$0 $17068$6e1ede2f @read.cnntp.org ...
          rio wrote:
          >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?
          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

          Comment

          • Maxim Yegorushkin

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

            On Nov 10, 10:22 am, James Kanze <james.ka...@gm ail.comwrote:
            On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
            wrote:
            >
            >
            >
            On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
            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:
                #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.
            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

            Comment

            • Hendrik Schober

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

              rio wrote:
              "Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
              news:4917cc4e$0 $17068$6e1ede2f @read.cnntp.org ...
              >rio wrote:
              >>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?
              >
              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

              Comment

              • Jeff Schwab

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

                rio wrote:
                "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.yegoru shkin@gmail.com said:
                >#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();
                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<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
                The vector's destructor deallocates the memory. Destruction can be a
                wonderful thing. :)

                Comment

                • Jeff Schwab

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

                  James Kanze wrote:
                  On Nov 7, 7:21 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
                  >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.yego rush...@gmail.c omsaid:
                  >>>>> namespace std {
                  >>>>> template<class A1, class A2>
                  >>>>> ostream& operator<<(ostr eam& s, vector<A1, A2const& vec)
                  >>>>Which has undefined behavior.
                  >>>The correct alternative, AIUI:
                  >>>template<typ ename T>
                  >>>std::ostream & operator<<(std: :ostream& out, std::vector<Tco nst& 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_whate ver 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.

                  Comment

                  • James Kanze

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

                    On Nov 10, 6:29 am, "rio" <a...@b.cwrot e:
                    "rio" <a...@b.cha scritto nel
                    messaggionews:4 916aba2$0$40315 $4fafbaef@reade r5.news.tin.it. ..
                    "Kai-Uwe Bux" <jkherci...@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.
                    i know max(std::size_t ) >= max(vector::siz e_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_ty pe, it's safe to
                    say that v.size() <= max( vector::size_ty pe ). But if
                    vector::size_ty pe 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: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

                    • James Kanze

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

                      On Nov 10, 12:47 pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
                      wrote:
                      On Nov 10, 10:22 am, James Kanze <james.ka...@gm ail.comwrote:
                      On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
                      wrote:
                      On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
                      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:
                          #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.
                      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: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

                      • Maxim Yegorushkin

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

                        On Nov 11, 9:24 am, James Kanze <james.ka...@gm ail.comwrote:
                        On Nov 10, 12:47 pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
                        wrote:
                        >
                        >
                        >
                        On Nov 10, 10:22 am, James Kanze <james.ka...@gm ail.comwrote:
                        On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
                        wrote:
                        On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
                        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:
                            #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.
                        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

                        Comment

                        • Hendrik Schober

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

                          Maxim Yegorushkin wrote:
                          On Nov 11, 9:24 am, James Kanze <james.ka...@gm ail.comwrote:
                          >On Nov 10, 12:47 pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.comwr ote:
                          >>On Nov 10, 10:22 am, James Kanze <james.ka...@gm ail.comwrote:
                          >>>On Nov 10, 10:19 am, Maxim Yegorushkin <maxim.yegorush ...@gmail.comwr ote:
                          >>>>On Nov 7, 12:17 pm, Pete Becker <p...@versatile coding.comwrote :
                          >>>>>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:
                          >>>>>> #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. [...]
                          >>>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

                          Comment

                          • Maxim Yegorushkin

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

                            On Nov 11, 11:20 am, Hendrik Schober <spamt...@gmx.d ewrote:

                            []
                              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

                            Comment

                            • Maxim Yegorushkin

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

                              On Nov 11, 1:54 pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
                              wrote:
                              On Nov 11, 11:20 am, Hendrik Schober <spamt...@gmx.d ewrote:
                              >
                              []
                              >
                                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_it erator<Map::val ue_type>(std::c out)
                              );
                              }

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

                              --
                              Max

                              Comment

                              • Hendrik Schober

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

                                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.d ewrote:
                                >>
                                >[]
                                >>
                                >> 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_it erator<Map::val ue_type>(std::c out)
                                );
                                }
                                >
                                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_ost ream<>' and 'val'
                                being an 'std::pair<>'. Why doesn't this find the global
                                operator?
                                Max
                                Schobi

                                Comment

                                Working...