STL question

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

    STL question

    Is there any way to use the STL algorithm for_each if my container
    contains pointers? For example,

    class A
    {
    int a;
    virtual void print (void) {cout << a << endl;}
    };
    class B: public A
    {
    int b;
    virtual void print (void) {cout << a << "," << b << endl;}
    }

    I want to have a list that I can call print() on for each member, so I
    figured vector <A*>. Is there anyway to get the following with
    for_each?

    vector <A*>::iterato r i;
    for (i=list.begin() ; i<list.end(); ++i) (*i)->print();

    Russ
  • Jonathan Turkanis

    #2
    Re: STL question

    "Rusty" <russR-E-M-O-V-Eford@shaw.ca> wrote in message
    news:b7tl00l2po j67i28cmesau5da c7ce17ulk@4ax.c om...[color=blue]
    > Is there any way to use the STL algorithm for_each if my container
    > contains pointers? For example,
    >
    > class A
    > {
    > int a;
    > virtual void print (void) {cout << a << endl;}
    > };
    > class B: public A
    > {
    > int b;
    > virtual void print (void) {cout << a << "," << b << endl;}
    > }
    >
    > I want to have a list that I can call print() on for each member, so[/color]
    I[color=blue]
    > figured vector <A*>. Is there anyway to get the following with
    > for_each?
    >[/color]

    struct Printer : std::unary_func tion<A*, void> {
    void operator() (A* a) const { /* write to cout */ }
    }

    std::for_each(l ist.begin(), list.end(), Printer());

    HTH.

    Jonathan


    Comment

    • Jacques Labuschagne

      #3
      Re: STL question

      Rusty wrote:[color=blue]
      > Is there any way to use the STL algorithm for_each if my container
      > contains pointers? For example,
      >
      > class A
      > {
      > int a;
      > virtual void print (void) {cout << a << endl;}
      > };
      > class B: public A
      > {
      > int b;
      > virtual void print (void) {cout << a << "," << b << endl;}
      > }
      >
      > I want to have a list that I can call print() on for each member, so I
      > figured vector <A*>. Is there anyway to get the following with
      > for_each?[/color]

      Sure..

      struct call_print{
      void operator()(A* a){ a->print(); }
      };

      and then

      for_each(v.begi n(), v.end(), call_print());
      [color=blue]
      >
      > vector <A*>::iterato r i;
      > for (i=list.begin() ; i<list.end(); ++i) (*i)->print();[/color]

      Don't call your vector 'list', there's already a std::list class.
      [color=blue]
      >
      > Russ[/color]

      Comment

      • Daniel T.

        #4
        Re: STL question

        Rusty <russR-E-M-O-V-Eford@shaw.ca> wrote:
        [color=blue]
        > Is there any way to use the STL algorithm for_each if my container
        > contains pointers? For example,
        >
        > class A
        > {
        > int a;
        > virtual void print (void) {cout << a << endl;}
        > };
        > class B: public A
        > {
        > int b;
        > virtual void print (void) {cout << a << "," << b << endl;}
        > }
        >
        > I want to have a list that I can call print() on for each member, so I
        > figured vector <A*>. Is there anyway to get the following with
        > for_each?
        >
        > vector <A*>::iterato r i;
        > for (i=list.begin() ; i<list.end(); ++i) (*i)->print();[/color]

        for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );

        Comment

        • Jacques Labuschagne

          #5
          Re: STL question

          Daniel T. wrote:[color=blue][color=green]
          >>vector <A*>::iterato r i;
          >>for (i=list.begin() ; i<list.end(); ++i) (*i)->print();[/color]
          >
          >
          > for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );[/color]

          Hang on, it's a vector of pointers... Surely there's no way of getting
          around the extra functor to dereference the pointer.

          Jacques

          Comment

          • Jerry Coffin

            #6
            Re: STL question

            In article <5VCOb.17855$ws .2199935@news02 .tsnz.net>,
            jacques@clawshr imp.com says...[color=blue]
            > Rusty wrote:[color=green]
            > > Is there any way to use the STL algorithm for_each if my container
            > > contains pointers? For example,
            > >
            > > class A
            > > {
            > > int a;
            > > virtual void print (void) {cout << a << endl;}
            > > };
            > > class B: public A
            > > {
            > > int b;
            > > virtual void print (void) {cout << a << "," << b << endl;}
            > > }
            > >
            > > I want to have a list that I can call print() on for each member, so I
            > > figured vector <A*>. Is there anyway to get the following with
            > > for_each?[/color]
            >
            > Sure..
            >
            > struct call_print{
            > void operator()(A* a){ a->print(); }
            > };[/color]

            Using operator<< to do formatted printing of an object is a widely known
            idiom, so it's probably better (at least IMO) to use it to do this job.
            I'd change the definitions a little bit so the member functions take the
            stream to write to as a parameter instead of always writing to
            std::cout, and return the stream they're writing to.

            class A
            {
            // I've defined it to take the ostream as a parameter instead of
            // always writing to cout.
            virtual std::ostream &print (std::ostream &os) const {return os<<a;}

            // since we've defined print to be private, make operator<< a friend
            // so it can call print.
            friend std::ostream &operator<<(std ::ostream &, A const *);
            protected:
            // a can't be private if you're going to access it directly in B
            int a;
            public:
            A(int init) : a(init) {}
            };

            class B: public A
            {
            int b;
            std::ostream &print(std::ost ream &os) const {
            return os << a << "," << b;
            }
            public:
            B(int inita, int initb) : A(inita), b(initb) {}
            };

            and then add the definition of operator<<:

            std::ostream &operator<<(std ::ostream &os, A const *a) {
            return a->print(os);
            }

            IMO, std::for_each isn't really the best tool for the job at hand
            either. We're copying the contents of the vector to a stream, so
            std::copy is really the algorithm for the job at hand:

            std::ostream_it erator<A*> out(std::cout, "\n");
            std::vector<A*> a;

            // code to populate 'a' elided.

            std::copy(a.beg in(), a.end(), out);

            --
            Later,
            Jerry.

            The universe is a figment of its own imagination.

            Comment

            • Jonathan Turkanis

              #7
              Re: STL question


              "Jacques Labuschagne" <jacques@clawsh rimp.com> wrote in message
              news:0cFOb.1788 2$ws.2203713@ne ws02.tsnz.net.. .[color=blue]
              > Daniel T. wrote:[color=green][color=darkred]
              > >>vector <A*>::iterato r i;
              > >>for (i=list.begin() ; i<list.end(); ++i) (*i)->print();[/color]
              > >
              > >
              > > for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );[/color]
              >
              > Hang on, it's a vector of pointers... Surely there's no way of[/color]
              getting[color=blue]
              > around the extra functor to dereference the pointer.
              >
              > Jacques
              >[/color]

              mem_fun returns a function object taking a pointer argument, so this
              should work. Of course, it only addresses the example, not the general
              problem.

              Jonathan


              Comment

              • Jacques Labuschagne

                #8
                Re: STL question

                Jonathan Turkanis wrote:[color=blue]
                > mem_fun returns a function object taking a pointer argument, so this
                > should work. Of course, it only addresses the example, not the general
                > problem.[/color]

                Right you are...

                Thanks,
                Jacques

                Comment

                • Jumbo

                  #9
                  Re: STL question


                  "Rusty" <russR-E-M-O-V-Eford@shaw.ca> wrote in message
                  news:b7tl00l2po j67i28cmesau5da c7ce17ulk@4ax.c om...[color=blue]
                  > Is there any way to use the STL algorithm for_each if my container
                  > contains pointers? For example,
                  >
                  > class A
                  > {
                  > int a;
                  > virtual void print (void) {cout << a << endl;}
                  > };
                  > class B: public A
                  > {
                  > int b;
                  > virtual void print (void) {cout << a << "," << b << endl;}
                  > }
                  >
                  > I want to have a list that I can call print() on for each member, so I
                  > figured vector <A*>. Is there anyway to get the following with
                  > for_each?
                  >
                  > vector <A*>::iterato r i;
                  > for (i=list.begin() ; i<list.end(); ++i) (*i)->print();
                  >
                  > Russ[/color]

                  Yes see code below:

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

                  using namespace std;

                  class Print{
                  public:
                  void operator()(cons t int* i)
                  {
                  cout<< *i << '\n';
                  }
                  };

                  int main(){
                  Print print;
                  vector<int*,all ocator<int> > intArr(3);
                  int x=1;
                  int y=2;
                  int z=3;
                  intArr[0] = &x;
                  intArr[1] = &y;
                  intArr[2] = &z;

                  for_each( intArr.begin(), intArr.end(), print);

                  return 0;
                  }


                  HTH.





                  Comment

                  • Daniel T.

                    #10
                    Re: STL question

                    Jacques Labuschagne <jacques@clawsh rimp.com> wrote:
                    [color=blue]
                    > Daniel T. wrote:[color=green][color=darkred]
                    > >>vector <A*>::iterato r i;
                    > >>for (i=list.begin() ; i<list.end(); ++i) (*i)->print();[/color]
                    > >
                    > >
                    > > for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );[/color]
                    >
                    > Hang on, it's a vector of pointers... Surely there's no way of getting
                    > around the extra functor to dereference the pointer.[/color]

                    mem_fun returns a functor that dereferences the pointer.

                    Comment

                    • Daniel T.

                      #11
                      Re: STL question

                      "Jonathan Turkanis" <technews@kanga roologic.com> wrote:[color=blue]
                      > "Jacques Labuschagne" <jacques@clawsh rimp.com> wrote:[color=green]
                      > > Daniel T. wrote:[color=darkred]
                      > > >>vector <A*>::iterato r i;
                      > > >>for (i=list.begin() ; i<list.end(); ++i) (*i)->print();
                      > > >
                      > > >
                      > > > for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );[/color]
                      > >
                      > > Hang on, it's a vector of pointers... Surely there's no way of[/color]
                      > getting[color=green]
                      > > around the extra functor to dereference the pointer.
                      > >
                      > > Jacques
                      > >[/color]
                      >
                      > mem_fun returns a function object taking a pointer argument, so this
                      > should work.[/color]

                      Of course it should work, this is exactly the type of problem that
                      mem_fun was designed to solve.

                      [color=blue]
                      > Of course, it only addresses the example, not the general
                      > problem.[/color]

                      It does address the general problem which was (from the OP):[color=blue]
                      > Is there any way to use the STL algorithm for_each if my container
                      > contains pointers?[/color]

                      The answer is, "Yes, one way is to use mem_fun."

                      Comment

                      • Jonathan Turkanis

                        #12
                        Re: STL question


                        "Daniel T." <postmaster@eat hlink.net> wrote in message
                        news:postmaster-D6484F.23331518 012004@news02.e ast.earthlink.n et...[color=blue]
                        > "Jonathan Turkanis" <technews@kanga roologic.com> wrote:[color=green]
                        > > "Jacques Labuschagne" <jacques@clawsh rimp.com> wrote:[color=darkred]
                        > > > Daniel T. wrote:
                        > > > >>vector <A*>::iterato r i;
                        > > > >>for (i=list.begin() ; i<list.end(); ++i) (*i)->print();
                        > > > >
                        > > > >
                        > > > > for_each( vec.begin(), vec.end(), mem_fun( &A::print ) );
                        > > >
                        > > > Hang on, it's a vector of pointers... Surely there's no way of[/color]
                        > > getting[color=darkred]
                        > > > around the extra functor to dereference the pointer.
                        > > >
                        > > > Jacques
                        > > >[/color]
                        > >
                        > > mem_fun returns a function object taking a pointer argument, so[/color][/color]
                        this[color=blue][color=green]
                        > > should work.[/color]
                        >
                        > Of course it should work, this is exactly the type of problem that
                        > mem_fun was designed to solve.
                        >[/color]

                        Would you feel better if I said 'does' instead of 'should'? I know it
                        works; it was a normative 'should'.
                        [color=blue]
                        >[color=green]
                        > > Of course, it only addresses the example, not the general
                        > > problem.[/color]
                        >
                        > It does address the general problem which was (from the OP):[color=green]
                        > > Is there any way to use the STL algorithm for_each if my container
                        > > contains pointers?[/color]
                        >[/color]

                        I don't we disagree about anything important. The more general problem
                        is how to iterate over a container of pointers when the operation you
                        wish to perform doesn't happen to be a member function.

                        Jonathan


                        Comment

                        • Martijn Lievaart

                          #13
                          Re: STL question

                          On Sun, 18 Jan 2004 21:08:56 +0000, Rusty wrote:
                          [color=blue]
                          > Is there any way to use the STL algorithm for_each if my container
                          > contains pointers? For example,
                          >
                          > class A
                          > {
                          > int a;
                          > virtual void print (void) {cout << a << endl;}
                          > };
                          > class B: public A
                          > {
                          > int b;
                          > virtual void print (void) {cout << a << "," << b << endl;}
                          > }
                          >
                          > I want to have a list that I can call print() on for each member, so I
                          > figured vector <A*>. Is there anyway to get the following with
                          > for_each?
                          >
                          > vector <A*>::iterato r i;
                          > for (i=list.begin() ; i<list.end(); ++i) (*i)->print();
                          >
                          > Russ[/color]

                          vector <A*>::iterato r i;
                          for_each (list.begin(), list.end(), mem_fun(&A::pri nt));

                          HTH,
                          M4

                          Comment

                          • Daniel T.

                            #14
                            Re: STL question

                            "Jonathan Turkanis" <technews@kanga roologic.com> wrote:
                            [color=blue]
                            > The more general problem
                            > is how to iterate over a container of pointers when the operation you
                            > wish to perform doesn't happen to be a member function.[/color]

                            That's easy too.

                            for_each( vec.begin(), vec.end(), myFunc );

                            for_each works fine with function pointers.

                            If the function happens to be in a different object. IE

                            class A { };
                            class B {
                            public:
                            void func( A* a );
                            };

                            vector<A*> vec;
                            B b;

                            Then one simply does this:

                            for_each( vec.begin(), vec.end(), bind1st( mem_fun(&B::fun c), &b ) );

                            Comment

                            • Jonathan Turkanis

                              #15
                              Re: STL question

                              "Daniel T." <postmaster@eat hlink.net> wrote in message
                              news:postmaster-741053.08062119 012004@news02.e ast.earthlink.n et...[color=blue]
                              > "Jonathan Turkanis" <technews@kanga roologic.com> wrote:
                              >[color=green]
                              > > The more general problem
                              > > is how to iterate over a container of pointers when the operation[/color][/color]
                              you[color=blue][color=green]
                              > > wish to perform doesn't happen to be a member function.[/color]
                              >
                              > That's easy too.
                              >
                              > for_each( vec.begin(), vec.end(), myFunc );
                              >
                              > for_each works fine with function pointers.
                              >[/color]

                              This is what I mentioned in my original post.

                              I know how to use the STL. What is your point?

                              Jonathan


                              Comment

                              Working...