POV-Ray : Newsgroups : povray.off-topic : Standard libraries : Re: Standard libraries Server Time
6 Sep 2024 15:19:07 EDT (-0400)
  Re: Standard libraries  
From: Nicolas Alvarez
Date: 7 Mar 2009 17:52:37
Message: <49b2fab5@news.povray.org>
Darren New wrote:
> Warp wrote:
>>   Another example: You could give std::sort() a comparator as a lambda
>> function which has access to the variables in the local scope, something
>> which is very laborious to do currently.
> 
> Hmmm. OK, thanks. I can see where something like that could be convenient.
> Most places I've seen that need that sort of thing pass in a "client data"
> sort of opaque pointer to allow it, so I guess this new stuff could
> obviate the need to design that in at the application layer.

In C, the standard qsort() function takes a function pointer and (I think)
a "client data" void pointer. You have to put your state in a struct, send
the pointer as client data, then in your comparator function get the data
through the pointer.

In C++, the standard std::sort template function takes a comparator functor.
Using functors (which can be an instance of a stateful class, or can be a
plain old function) instead of passing a "client data" pointer is quite
common in C++.

Here is a [useless in practice] example where the comparator takes an
initialization parameter (whether to sort descending or ascending), and
also keeps state that can be retrieved later (how many times the comparison
function was called).

struct MyComparator {
    bool reverse_mode;
    int comparison_count;

    MyComparator(bool reverse) {
        reverse_mode = reverse;
        comparison_count = 0;
    }

    bool operator()(int a, int b) {
        comparison_count++;
        if (reverse_mode) {
            return b < a;
        } else {
            return a < b;
        }
    }
};

std::vector<int> list;

MyComparator c(false);
std::sort(list.begin(), list.end(), c);

cout << "Comparator called " << c.comparison_count << " times\n";

If you don't need to retrieve any data after the comparison, you could also
do this:

std::sort(list.begin(), list.end(), MyComparator(false));


With lambdas, you can use "closures" to keep state, so you don't need a
separate class/struct declared elsewhere:

std::vector<int> list;
int comparison_count=0;

std::sort(list.begin(), list.end(), [&comparison_count](int a, int b) {
    comparison_count++;
    return a < b;
});

Even if you don't want to keep any state (and leave the [] empty to use no
closures), it's still useful to declare the comparison code right next to
the std::sort call, instead of in a function/class possibly far away in
the .cpp file. This is the part I said was similar to string literals (you
know how in assembler you need a manually-made list of strings at the
beginning of the program? :P).


Post a reply to this message

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