stl and standard library functions

Discussion in 'C++' started by sks_cpp, Jun 28, 2003.

  1. sks_cpp

    sks_cpp Guest

    I am somewhat new to STL and the plethora of library functions they have. I
    looked at sgi's stl info. and I was overwhelmed so I thought I would present
    my question here.

    I have
    std::map<WWN*, Drive*> m_Drives

    I want to take that and run a functor through all of them (the functor has
    Drive* has the parameter type) and whichever ones meet the predicate functor
    will need to be added to a list of Drive*s. (std::list<Drive*> driveList)

    I can write a loop to do this and in fact, I will do it here to show what I
    am trying to achieve. But I would rather use the library functions, if
    possible.

    for ( mapIter i = m_Drives.begin(); i != m_Drives.end(); ++i )
    {
    if ( i.second->getType == someType && i.second->getCapacity >=
    someCapacity )
    driveList.push_back(i.second);
    }

    My code may not compile since I just wrote it on the fly.
    My for loop is only few lines long so maybe doing that is better than using
    the standard library functions.

    However, I read part of Scott Meyers's Effective STL stuff and he says that
    standard functions are efficient, correct, and maintainable. Anyway, any
    help would be nice.

    Thanks.
    sks_cpp, Jun 28, 2003
    #1
    1. Advertising

  2. sks_cpp escribió:

    > I have
    > std::map<WWN*, Drive*> m_Drives
    >
    > I want to take that and run a functor through all of them (the functor has
    > Drive* has the parameter type) and whichever ones meet the predicate functor
    > will need to be added to a list of Drive*s. (std::list<Drive*> driveList)
    >
    > I can write a loop to do this and in fact, I will do it here to show what I
    > am trying to achieve. But I would rather use the library functions, if
    > possible.
    >
    > for ( mapIter i = m_Drives.begin(); i != m_Drives.end(); ++i )
    > {
    > if ( i.second->getType == someType && i.second->getCapacity >=
    > someCapacity )
    > driveList.push_back(i.second);
    > }


    Something like that (untested):

    class SelectDrive {
    public:
    SelectDrive (std::list <Drive *> & driveList, Type type, int capacity)
    :
    driveList (driveList), type (type), capacity (capacity)
    { }
    void operator () (const std::map <WWN *, Drive *>::value_type & i)
    {
    if (i.second->getType == someType && i.second->getCapacity >=
    capacity)
    driveList.push_back (i.second);
    }
    private:
    std::list <Drive *> & driveList;
    Type type;
    int capacity;
    };

    An use as:

    std::for_each (m_Drives.begin (), m_Drives.end (),
    SelectDrive (driveList, someType, someCapacity) );

    Regards.
    =?iso-8859-1?Q?Juli=E1n?= Albo, Jun 28, 2003
    #2
    1. Advertising

  3. sks_cpp

    Jerry Coffin Guest

    In article <BSiLa.338099$>,
    says...
    > I am somewhat new to STL and the plethora of library functions they have. I
    > looked at sgi's stl info. and I was overwhelmed so I thought I would present
    > my question here.
    >
    > I have
    > std::map<WWN*, Drive*> m_Drives
    >
    > I want to take that and run a functor through all of them (the functor has
    > Drive* has the parameter type) and whichever ones meet the predicate functor
    > will need to be added to a list of Drive*s. (std::list<Drive*> driveList)


    std::remove_copy_if seems to be what you're looking for. Using this
    you'll have to reverse the sense of your predicate -- it copies
    elements, removing those for which the predicate is true, rather than
    only copying those for which it is true.

    // warning: untested code.
    bool your_predicate(std::pair<WWN*, Drive *> p) {
    return (p.second->getType != someType ||
    p.second->getCapacity < someCapacity);
    }

    std::remove_copy_if(m_drives.begin(), m_drives.end(),
    std::inserter(driveList, driveList.end()),
    your_predicate);

    Please don't ask me why the committee preferred remove_copy_if to
    copy_if -- I have no idea, and mostly disagree. At least to me, the
    name std::remove_copy_if sounds like it should be a variant of
    std::unique, or something on that order, but it's basically just the
    (unfortunately nonexistent) std::copy_if having a really bad hair day.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Jun 29, 2003
    #3
  4. sks_cpp

    sks_cpp Guest

    "Jerry Coffin" <> wrote in message
    news:...

    > std::remove_copy_if(m_drives.begin(), m_drives.end(),
    > std::inserter(driveList, driveList.end()),
    > your_predicate);


    I don't want to remove from the map - just insert the ones that meet the
    criteria into the list. Is that what the above code does? What does inserter
    do?

    > Please don't ask me why the committee preferred remove_copy_if to
    > copy_if -- I have no idea, and mostly disagree. At least to me, the
    > name std::remove_copy_if sounds like it should be a variant of
    > std::unique, or something on that order, but it's basically just the
    > (unfortunately nonexistent) std::copy_if having a really bad hair day.


    I might have to agree with you here.

    Thanks for your suggestions/comments.
    sks_cpp, Jun 29, 2003
    #4
  5. sks_cpp

    sks_cpp Guest

    "Julián Albo" <> wrote in message
    news:...
    > class SelectDrive {
    > public:
    > SelectDrive (std::list <Drive *> & driveList, Type type, int capacity)
    > :
    > driveList (driveList), type (type), capacity (capacity)
    > { }
    > void operator () (const std::map <WWN *, Drive *>::value_type & i)
    > {
    > if (i.second->getType == someType && i.second->getCapacity >=
    > capacity)
    > driveList.push_back (i.second);
    > }
    > private:
    > std::list <Drive *> & driveList;
    > Type type;
    > int capacity;
    > };


    Thanks for your coments. I found something interesting with your operator
    method. It takes "value_type" as its parameter. Now, could it have taken a
    pair? What if you overload the operators with ambiguous parameters, such as
    "value_type" as you have it and "pair<WWN*, Drive*>" - is that a compiler
    error or does one have precedence over the other?

    Thanks.
    sks_cpp, Jun 29, 2003
    #5
  6. sks_cpp

    Jerry Coffin Guest

    In article <qlILa.345190$>,
    says...
    > "Jerry Coffin" <> wrote in message
    > news:...
    >
    > > std::remove_copy_if(m_drives.begin(), m_drives.end(),
    > > std::inserter(driveList, driveList.end()),
    > > your_predicate);

    >
    > I don't want to remove from the map - just insert the ones that meet the
    > criteria into the list.


    That's part of what I meant about remove_copy_if having a deceiving
    name. It leaves the contents of the original container unaffected. It
    just removes the items from the copy -- which is to say that if they
    meet the criteria, it doesn't copy them.

    > Is that what the above code does? What does inserter do?


    Yes. std::inserter is just a utility function that creates an
    insert_iterator for a particular spot in a particular container. In
    case you're not familiar with insert_iterators (and
    back_insert_iterators, etc.) they're iterators that insert items into a
    collection -- i.e. they don't just overwrite items at locations, but
    create space for new ones. e.g. with something like this:

    std::vector x, y;

    for(int i=0; i<10; ++i)
    x.push_back(i);

    std::copy(x.begin(), x.end(), back_inserter(y, y.end());

    the back_inserter creates an iterator that basically does a push_back to
    put each item into y. This saves you from having to resize y to the
    correct size ahead of time, which would be trivial in the situation
    above, but much more difficult in a situation like yours, where you
    don't know ahead of time how many items you'll be inserting into the
    list.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Jun 30, 2003
    #6
  7. sks_cpp

    Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > std::copy(x.begin(), x.end(), back_inserter(y, y.end());


    Oops -- with back_inserter, you don't need to specify an iterator, since
    it always inserts at the back. I.e. the call above should be just:

    std::copy(x.begin(), x.end(), back_inserter(y));

    with std::inserter, you have to specify an iterator as the point where
    the insertion(s) will take place, since (unlike back_inserter) it's not
    implicit.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Jun 30, 2003
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xiangliang Meng
    Replies:
    1
    Views:
    1,592
    Victor Bazarov
    Jun 21, 2004
  2. J Wang

    where standard library functions?

    J Wang, Apr 10, 2004, in forum: C Programming
    Replies:
    1
    Views:
    382
    Malcolm
    Apr 10, 2004
  3. steve.leach

    How standard is the standard library?

    steve.leach, Apr 18, 2005, in forum: Python
    Replies:
    1
    Views:
    390
    Christos TZOTZIOY Georgiou
    Apr 18, 2005
  4. funkyj
    Replies:
    5
    Views:
    1,125
    funkyj
    Jan 20, 2006
  5. Replies:
    5
    Views:
    862
Loading...

Share This Page