POV-Ray : Newsgroups : povray.off-topic : To anyone who has worked with boost : Re: To anyone who has worked with boost Server Time
28 Jul 2024 20:34:32 EDT (-0400)
  Re: To anyone who has worked with boost  
From: Warp
Date: 17 Feb 2013 16:35:58
Message: <51214d3e@news.povray.org>
Anthony D. Baye <Sha### [at] spamnomorehotmailcom> wrote:
> > You do understand what the idea with functors is?

> apparently not.

If something takes just a function pointer, then everything it has to
work with is what it gets as parameters and nothing more. The function in
question cannot have unique data that it handles.

(You could, of course, have some static data that it handles, but that
data would be shared by all calls to that function. They cannot have
separate data for separate use cases.)

In typical C libraries this limitation is circumvented by the library
taking some void* alongside the function pointer, and passing that void*
to the function in question, which can use that pointer for whatever data
it wants. Of course this is cumbersome, not type-safe, and can be
problematic with respect to memory management. (It also adds a degree of
inefficiency that technically wouldn't be necessary if no ancillary data
is used.)

A functor, however, is not a function, but an object, and therefore it
can have its own data that it handles.

One could ask why couldn't the templates just take an object directly,
rather than a functor? It could be a convention for them to call a member
function with a certain name.

The answer is convenience and flexibility. Since calling a functor has
the exact same syntax as calling a regular function, you can give the
template either one. This avoids code repetition if you want to support
both regular functions and functors, as well as maximizes optimization
possibilities for the compiler.

As an example, you could call eg. std::sort with a comparison function
like:

    bool compareInt(int a, int b) { return a > b; }
    ...
        std::sort(v.begin(), v.end(), compareInt);

But let's say that you want to do something fancy, like for example count
how many comparisons are made during sorting. You can use a functor to do
that. For example like this:

    struct CompareInt
    {
        unsigned comparisons = 0;

        bool operator()(int a, int b) const
        {
            ++comparisons;
            return a > b;
        }
    };
    ...
        CompareInt comparator;
        std::sort(v.begin(), v.end(), comparator);
        std::cout << comparator.comparisons
                  << " comparisons were made\n";

In both cases std::sort() will internally make calls like

    if(comparator(value1, value2)) ...

If you were implementing something that uses a functor, like eg. your
own sorting algorithm, this is nice from that perspective because said
implementation doesn't need to care whether the comparator is a regular
function or a functor (or even a lambda.)

-- 
                                                          - Warp


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.