std::find_if in vector

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • eiji.anonremail@googlemail.com

    std::find_if in vector

    I would like to search in a vector depending on "a" or "a and b"
    without the overhead of creating a Foo object or another predicate
    class.

    Is that possible? Using a member function pointer or a global static
    function?
    Right now I have this, but I don't like it.

    ------------------------------Example
    code----------------------------------------------
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <functional>

    class Foo {

    public:
    Foo(int aa, int bb, int cc):a(aa),b(bb) ,c(cc) {}

    bool operator()(cons t Foo& f) {
    return (GetA() == f.GetA() &&
    GetB() == f.GetB() &&
    GetC() == f.GetC());
    }

    inline int GetA() const {return a;}
    inline int GetB() const {return b;}
    inline int GetC() const {return c;}

    private:
    int a,b,c;
    };

    class Foo_eq_a : public std::unary_func tion<Foo, bool{
    public:
    explicit Foo_eq_a(int aa):a(aa) {}

    bool operator() (const Foo& f) const
    {
    return (f.GetA() == a);
    }
    private:
    int a;
    };
    class Foo_eq_ab : public std::unary_func tion<Foo, bool{
    public:
    explicit Foo_eq_ab(int aa, int bb):eq_a(aa),b( bb) {}

    bool operator() (const Foo& f) const
    {
    return (eq_a(f) && f.GetB() == b);
    }
    private:
    Foo_eq_a eq_a;
    int b;
    };

    int main()
    {
    std::vector<Foo foos;

    foos.push_back( Foo(1,1,1));
    foos.push_back( Foo(1,2,2));
    foos.push_back( Foo(1,2,3));


    std::vector<Foo >::const_iterat or citer;
    citer = std::find_if(fo os.begin(), foos.end(), Foo(1,2,3));
    if (citer != foos.end())
    std::cout << "operator() hit, okay" << std::endl;

    citer = std::find_if(fo os.begin(), foos.end(), Foo(1,2,4));
    if (citer == foos.end())
    std::cout << "operator() no hit, okay" << std::endl;


    citer = std::find_if(fo os.begin(), foos.end(), Foo_eq_ab(1,2)) ;
    if (citer == ++foos.begin())
    std::cout << "position 1, okay" << std::endl;

    system("Pause") ;
    }

    ----------------------------------
    Any suggestions?
    Thanks
  • Sam

    #2
    Re: std::find_if in vector

    eiji.anonremail @googlemail.com writes:
    I would like to search in a vector depending on "a" or "a and b"
    without the overhead of creating a Foo object or another predicate
    class.
    >
    Is that possible? Using a member function pointer or a global static
    function?
    Use std::ptr_fun to turn your global static function into a suitable
    function object.


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.9 (GNU/Linux)

    iEYEABECAAYFAkk RiwIACgkQx9p3GY HlUOKxMwCeLnLlb bFolNN+/LekQI21r/N1
    9uYAn160phJeQi1 S8oyI6qM2VfcA1B rx
    =uZ/K
    -----END PGP SIGNATURE-----

    Comment

    • Eric.Malenfant@gmail.com

      #3
      Re: std::find_if in vector

      eiji.anonrem... @googlemail.com a écrit :
      I would like to search in a vector depending on "a" or "a and b"
      without the overhead of creating a Foo object or another predicate
      class.
      Maybe a lambda?

      With:
      #include <boost/lambda/lambda.hpp>
      #include <boost/lambda/bind.hpp>
      namespace bl = boost::lambda;

      This:
      std::find_if(f. begin(), f.end(), (bl::bind(&Foo: :GetA, bl::_1) == 1)
      && (bl::bind(&Foo: :GetB, bl::_1) == 2));
      could replace:
      std::find_if(fo os.begin(), foos.end(), Foo_eq_ab(1,2)) ;

      Comment

      • eiji.anonremail@googlemail.com

        #4
        Re: std::find_if in vector


        Use std::ptr_fun to turn your global static function into a suitable
        function object.
        This is not possible, since you can not pass in arguments, from what I
        know.

        To turn this:
        citer = std::find_if(fo os.begin(), foos.end(), Foo_eq_ab(1,2)) ;

        into
        class Foo {
        ....
        public:
        static bool eq_ab(const Foo& f) {return false}
        ....
        };

        There is no possibility to pass "1,2".

        ??

        Comment

        • eiji.anonremail@googlemail.com

          #5
          Re: std::find_if in vector

          Maybe a lambda?
          >
          With:
          #include <boost/lambda/lambda.hpp>
          #include <boost/lambda/bind.hpp>
          namespace bl = boost::lambda;
          >
          This:
          std::find_if(f. begin(), f.end(), (bl::bind(&Foo: :GetA, bl::_1) == 1)
          && (bl::bind(&Foo: :GetB, bl::_1) == 2));
          could replace:
          std::find_if(fo os.begin(), foos.end(), Foo_eq_ab(1,2)) ;
          Two reasons why not:
          - boost is not an option :-/
          - I wan't to encapsulate (x == y && z == y ...) in one place. Using
          this approach, I would again have to change lot's of places when
          search pattern changes a bit. The search pattern and the call should
          be clean seperated as far as possible.

          Comment

          • Sam

            #6
            Re: std::find_if in vector

            eiji.anonremail @googlemail.com writes:

            >Use std::ptr_fun to turn your global static function into a suitable
            >function object.
            This is not possible, since you can not pass in arguments, from what I
            know.

            To turn this:
            citer = std::find_if(fo os.begin(), foos.end(), Foo_eq_ab(1,2)) ;

            into
            class Foo {
            ...
            public:
            static bool eq_ab(const Foo& f) {return false}
            ...
            };

            There is no possibility to pass "1,2".
            static bool Foo_eq_b(int n)
            {
            return Foo_eq_a_b(1, 2, n);
            }

            std::find_if(fo os.begin(), foos.end(), std::ptr_fun(Fo o_eq_b));

            … or whatever.


            -----BEGIN PGP SIGNATURE-----
            Version: GnuPG v1.4.9 (GNU/Linux)

            iEYEABECAAYFAkk SKugACgkQx9p3GY HlUOKZNwCfceupI UPeMG6bpdgnU2Gv EAHZ
            x1UAniHYA5+bfyf mn6EkVQKy8LIG8A ia
            =kF5q
            -----END PGP SIGNATURE-----

            Comment

            Working...