cout << vector<string>

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

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

    On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.d ewrote:
    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?
    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_ostr eam
    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

    Comment

    • Hendrik Schober

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

      Maxim Yegorushkin wrote:
      On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.d ewrote:
      >Maxim Yegorushkin wrote:
      [...]
      >> #include <map>
      >> #include <iostream>
      >> #include <iterator>
      >> // should be in namespace std::
      >> template<class T, class U>
      >> std::ostream& operator<<(std: :ostream& s, std::pair<T, Uconst& p)
      >> {
      >> return s << p.first << ' ' << p.second;
      >> }
      >> int main()
      >> {
      >> typedef std::map<int, intMap;
      >> Map m;
      >> std::copy(
      >> m.begin()
      >> , m.end()
      >> , std::ostream_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?
      >
      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_ostr eam
      and val is std::pair<int, int>, thus one associated namespace is std.
      int has no associated namespaces. So, the only namespace considered
      for expression "ostr << val" is std, which lacks a suitable
      operator<<().
      But lookup isn't ADL only. The enclosing namespaces are considered,
      too, aren't they? And the global namespaces is always enclosing.
      (I'm not saying you're wrong. I just don't understand this.)
      Max
      Schobi

      Comment

      • Maxim Yegorushkin

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

        On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.d ewrote:
        Maxim Yegorushkin wrote:
        On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.d ewrote:
        Maxim Yegorushkin wrote:
        [...]
        >    #include <map>
        >    #include <iostream>
        >    #include <iterator>
        >    // should be in namespace std::
        >    template<class T, class U>
        >    std::ostream& operator<<(std: :ostream& s, std::pair<T, Uconst& p)
        >    {
        >        return s << p.first << ' ' << p.second;
        >    }
        >    int main()
        >    {
        >        typedef std::map<int, intMap;
        >        Map m;
        >        std::copy(
        >              m.begin()
        >            , m.end()
        >            , std::ostream_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?
        >
        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_ostr eam
        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

        Comment

        • Hendrik Schober

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

          Maxim Yegorushkin wrote:
          On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.d ewrote:
          >Maxim Yegorushkin wrote:
          >>On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.d ewrote:
          >>>Maxim Yegorushkin wrote:
          >>[...]
          >>>> #include <map>
          >>>> #include <iostream>
          >>>> #include <iterator>
          >>>> // should be in namespace std::
          >>>> template<class T, class U>
          >>>> std::ostream& operator<<(std: :ostream& s, std::pair<T, Uconst& p)
          >>>> {
          >>>> return s << p.first << ' ' << p.second;
          >>>> }
          >>>> int main()
          >>>> {
          >>>> typedef std::map<int, intMap;
          >>>> Map m;
          >>>> std::copy(
          >>>> m.begin()
          >>>> , m.end()
          >>>> , std::ostream_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?
          >>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_ostr eam
          >>and val is std::pair<int, int>, thus one associated namespace is std.
          >>int has no associated namespaces. So, the only namespace considered
          >>for expression "ostr << val" is std, which lacks a suitable
          >>operator<<( ).
          > But lookup isn't ADL only. The enclosing namespaces are considered,
          > too, aren't they? And the global namespaces is always enclosing.
          > (I'm not saying you're wrong. I just don't understand this.)
          >
          At the second stage of the two-phase name lookup (at the point of
          template instantiation) it is ADL only.
          I'm trying to come up with some trivial example that
          illustrates this, but I fail. I have this

          #include <iostream>

          namespace N {
          struct test { };

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

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

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

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

          which compiles fine and gives the expected result.
          What am I still missing.
          Max
          Schobi

          Comment

          • Maxim Yegorushkin

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

            On Nov 11, 4:39 pm, Hendrik Schober <spamt...@gmx.d ewrote:
            Maxim Yegorushkin wrote:
            On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.d ewrote:
            Maxim Yegorushkin wrote:
            >On Nov 11, 2:40 pm, Hendrik Schober <spamt...@gmx.d ewrote:
            >>Maxim Yegorushkin wrote:
            >[...]
            >>>    #include <map>
            >>>    #include <iostream>
            >>>    #include <iterator>
            >>>    // should be in namespace std::
            >>>    template<class T, class U>
            >>>    std::ostream& operator<<(std: :ostream& s, std::pair<T, Uconst& p)
            >>>    {
            >>>        return s << p.first << ' ' << p.second;
            >>>    }
            >>>    int main()
            >>>    {
            >>>        typedef std::map<int, intMap;
            >>>        Map m;
            >>>        std::copy(
            >>>              m.begin()
            >>>            , m.end()
            >>>            , std::ostream_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?
            >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_ostr eam
            >and val is std::pair<int, int>, thus one associated namespace is std.
            >int has no associated namespaces. So, the only namespace considered
            >for expression "ostr << val" is std, which lacks a suitable
            >operator<<() .
              But lookup isn't ADL only. The enclosing namespaces are considered,
              too, aren't they? And the global namespaces is always enclosing.
              (I'm not saying you're wrong. I just don't understand this.)
            >
            At the second stage of the two-phase name lookup (at the point of
            template instantiation) it is ADL only.
            >
              I'm trying to come up with some trivial example that
              illustrates this, but I fail. I have this
            >
                 #include <iostream>
            >
                 namespace N {
                     struct test { };
            >
                     template< typename T >
                     void f(T) {  std::cout << "f(T)\n"; }
            >
                     void f(int) {  std::cout << "f(int)\n"; }
                 }
            >
                 template< typename T >
                 void g(T o) { f(o); }
            >
                 int main()
                 {
                     N::test t;
                     g(t);
                 }
            >
              which compiles fine and gives the expected result.
              What am I still missing.
            Your example should work just fine.

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

            namespace N {

            struct X {};

            void bar(struct overload_for_co mpilers_with_no _two_phase_look up&);

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

            }

            template<class Tvoid bar(T);

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

            --
            Max

            Comment

            • rio

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

              "Hendrik Schober" <spamtrap@gmx.d eha scritto nel messaggio
              news:gf972o$csj $2@hoshi.visyn. net...
              rio wrote:
              >"Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
              >news:4917cc4e$ 0$17068$6e1ede2 f@read.cnntp.or g...
              >>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'.
              ok
              what about relation between "size_t"
              and 'std::vector<T> ::size_type'?
              >[...]
              >
              Schobi

              Comment

              • rio

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


                "Jeff Schwab" <jeff@schwabcen ter.comha scritto nel messaggio
                news:2smdnb8oRr YL-YXUnZ2dnUVZ_qXi nZ2d@giganews.c om...
                rio wrote:
                The vector's destructor deallocates the memory. Destruction can be a
                wonderful thing. :)
                yes i know it, but it is better to know where it is done



                Comment

                • Kai-Uwe Bux

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

                  rio wrote:
                  "Hendrik Schober" <spamtrap@gmx.d eha scritto nel messaggio
                  news:gf972o$csj $2@hoshi.visyn. net...
                  >rio wrote:
                  >>"Kai-Uwe Bux" <jkherciueh@gmx .netha scritto nel messaggio
                  >>news:4917cc4e $0$17068$6e1ede 2f@read.cnntp.o rg...
                  >>>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'.
                  >
                  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

                  Comment

                  • Jeff Schwab

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

                    rio wrote:
                    "Jeff Schwab" <jeff@schwabcen ter.comha scritto nel messaggio
                    news:2smdnb8oRr YL-YXUnZ2dnUVZ_qXi nZ2d@giganews.c om...
                    >rio wrote:
                    >The vector's destructor deallocates the memory. Destruction can be a
                    >wonderful thing. :)
                    >
                    yes i know it, but it is better to know where it is done
                    C++ destruction is deterministic, well-defined, and fairly easy to
                    understand. The fact that something is taken care of by a destructor
                    doesn't mean you don't know where it's done. If you use automatic
                    allocation, destruction happens when the object goes out of scope.

                    Comment

                    • James Kanze

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

                      On Nov 13, 6:58 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                      rio wrote:
                      "Hendrik Schober" <spamt...@gmx.d eha scritto nel messaggio
                      news:gf972o$csj $2@hoshi.visyn. net...
                      rio wrote:
                      >"Kai-Uwe Bux" <jkherci...@gmx .netha scritto nel messaggio
                      >>news:4917cc4e $0$17068$6e1ede 2f@read.cnntp.o rg...
                      >>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'.
                      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>::diff erence_type. And vector<T>::diff erence_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: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

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

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

                        Comment

                        • James Kanze

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

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

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

                          --
                          James Kanze (GABI Software) email: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

                          • Hendrik Schober

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

                            Maxim Yegorushkin wrote:
                            On Nov 11, 4:39 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                            >Maxim Yegorushkin wrote:
                            >>On Nov 11, 3:36 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                            [...]
                            >>> But lookup isn't ADL only. The enclosing namespaces are considered,
                            >>> too, aren't they? And the global namespaces is always enclosing.
                            >>> (I'm not saying you're wrong. I just don't understand this.)
                            >>At the second stage of the two-phase name lookup (at the point of
                            >>template instantiation) it is ADL only.
                            > I'm trying to come up with some trivial example that
                            > illustrates this, but I fail. [...]
                            >
                            Here is a simplified version of the problem with
                            std::ostream_it erator<std::pai r< and a global
                            operator<<(std: :ostream&, std::pair<>):
                            >
                            namespace N {
                            >
                            struct X {};
                            >
                            void bar(struct overload_for_co mpilers_with_no _two_phase_look up&);
                            >
                            template<class Tvoid foo(T t) { bar(t); }
                            >
                            }
                            >
                            template<class Tvoid bar(T);
                            >
                            int main()
                            {
                            N::X x;
                            foo(x);
                            }
                            Thanks, I didn't know this.
                            I suppose the rationale is to limit the number of possibly
                            surprising overloads considered?
                            Max
                            Schobi

                            Comment

                            Working...