sorting a vector, functors, and std::binary_function

Discussion in 'C++' started by Christopher, Nov 28, 2007.

  1. Christopher

    Christopher Guest

    I used to just use a plain old function pointer is a call to
    std::sort.

    My colleagues are telling me that I need to use a "functor". Ok, I
    google and see that a functor is a class with a public method,
    operator () that does the comparison. Fine, no problem. What they fail
    to tell me is, what is the advantage to wrapping some comparison
    function in a class and calling it operator()?

    I also read that "functors" are supposed to be a class that wraps a
    function pointer and additionally holds a state. What kind of state,
    what is the typical scenario? I don't see any state data in any of my
    colleagues code...

    I also googled for examples on doing a sort upon a vector using this
    concept of a functor to get the syntax correct. I notice that one
    example derives his functor from std::binary_function. Google
    binary_function and see that it is described as "a base class for a
    functor", well that doesn't tell me much. Why do some of the examples
    I've found derive from std::binary_function while others do not?

    Thanks!
    Christopher, Nov 28, 2007
    #1
    1. Advertising

  2. Christopher

    red floyd Guest

    Christopher wrote:
    > I used to just use a plain old function pointer is a call to
    > std::sort.
    >
    > My colleagues are telling me that I need to use a "functor". Ok, I
    > google and see that a functor is a class with a public method,
    > operator () that does the comparison. Fine, no problem. What they fail
    > to tell me is, what is the advantage to wrapping some comparison
    > function in a class and calling it operator()?
    >


    It can be inlined by std::sort().

    Using a function pointer is perfectly legitimate. A functor is
    "anything that looks and behaves like a function".
    red floyd, Nov 28, 2007
    #2
    1. Advertising

  3. Christopher wrote:

    > What they fail
    > to tell me is, what is the advantage to wrapping some comparison
    > function in a class and calling it operator()?


    You can't pass a (non-static) member function since the hidden object
    pointer isn't typically part of the function's pointer; hence this
    mechanism.
    I think that's the main reason -- basically a workaround.
    Matthias Buelow, Nov 28, 2007
    #3
  4. Christopher wrote:
    > I also read that "functors" are supposed to be a class that wraps a
    > function pointer and additionally holds a state. What kind of state,
    > what is the typical scenario?


    Please consider the code below to be pseudo-code.

    // Contrived textbook example with constant state:

    struct mul {
    const int multiplier;
    mul(int multiplier_): multiplier(multiplier_) {}
    void operator()(int n) { n *= multiplier; }
    };

    mul quadruple(4);
    mul tripple(3);

    vector<int> i = .......;
    foreach(i.begin, i.end, quadruple);


    // You could imagine non-const state in something like.

    struct find_min_max .......
    log_min_max minmax;
    foreach(i.begin(), i.end(), minmax);


    // A real example that I use is:

    charset_converter utf8_to_8859_1("utf8","iso8859-1");

    while (!end-of-input) {
    s += utf8_to_8859_1(next_bit);
    }

    Here the functor state is any partial multi-byte characters.



    Regards,

    Phil.
    Phil Endecott, Nov 28, 2007
    #4
  5. Christopher

    James Kanze Guest

    On Nov 28, 6:56 pm, Christopher <> wrote:
    > I used to just use a plain old function pointer is a call to
    > std::sort.


    > My colleagues are telling me that I need to use a "functor".


    Don't believe them.

    > Ok, I google and see that a functor is a class with a public
    > method, operator () that does the comparison. Fine, no
    > problem. What they fail to tell me is, what is the advantage
    > to wrapping some comparison function in a class and calling it
    > operator()?


    The use of a functor means that there is a separate
    instantiation of std::sort for each function (since each functor
    has a different type), and that the actual function is known in
    the instantiation of std::sort. This can (in some cases) result
    in slightly faster code, because the compiler can inline the
    comparison. It can (in certain other cases) result in code
    bloat, because the compiler must generate a separate
    instantiation of the std::sort function template for each
    different function. 99% of the time, it doesn't matter.

    > I also read that "functors" are supposed to be a class that wraps a
    > function pointer and additionally holds a state. What kind of state,
    > what is the typical scenario? I don't see any state data in any of my
    > colleagues code...


    First, it doesn't wrap a function pointer; it has a member
    function which does the job. Secondly, it's very, very rare for
    a binary predicate to contain state. Other functors often do,
    however: the predicate for std::find_if may (in fact, usually
    will) contain the key you're looking for. And even binary
    precidates can contain state; if you want to do a case
    insensitive comparison of strings, for example, you might embed
    a pointer to the desired std::ctype facet in the predicate, for
    example.

    > I also googled for examples on doing a sort upon a vector
    > using this concept of a functor to get the syntax correct. I
    > notice that one example derives his functor from
    > std::binary_function. Google binary_function and see that it
    > is described as "a base class for a functor", well that
    > doesn't tell me much. Why do some of the examples I've found
    > derive from std::binary_function while others do not?


    No real reason. When you start composing several functors, it
    becomes necessary that the functors being composed contain
    typedefs indicating their argument and return value types. The
    class std::binary_function provides these, but you can also
    provide them manually. And they're only used when you start
    composing, using things like std::bind2nd. Which means that if
    you're writing a local functor, which can't be seen outside your
    source, there's no real point in them at all.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Nov 29, 2007
    #5
    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. Jason Heyes
    Replies:
    8
    Views:
    708
    Andrew Koenig
    Jan 15, 2006
  2. news.online.no
    Replies:
    2
    Views:
    482
    Daniel T.
    Jan 30, 2006
  3. yurec

    std::binary_function

    yurec, Mar 28, 2008, in forum: C++
    Replies:
    9
    Views:
    939
    Pete Becker
    Mar 31, 2008
  4. Frank Bergemann

    look-up table for std::binary_function's

    Frank Bergemann, Apr 23, 2008, in forum: C++
    Replies:
    0
    Views:
    303
    Frank Bergemann
    Apr 23, 2008
  5. Frank Bergemann

    look-up table for std::binary_function's

    Frank Bergemann, Apr 23, 2008, in forum: C++
    Replies:
    1
    Views:
    424
    Frank Bergemann
    Apr 23, 2008
Loading...

Share This Page