c++classc++11lambdaclass-members

Clean way to put lambda in class definition


I have code that works just fine, in a local function:

struct Divider
{
public:
    size_t factor;
    size_t next;
};

void foo()
{
    auto cmp = [](const Divider& x, const Divider& y) { return x.next > y.next; };
    std::priority_queue < Divider, std::vector<Divider>, decltype(cmp)> sieve(cmp);
    // ...
}

I would now like to move my sieve variable into a class. I can write the following monstrosity:

class Bar
{
    inline static auto cmp = [](const Divider& x, const Divider& y) { return x.next > y.next; };
    std::priority_queue < Divider, std::vector<Divider>, decltype(cmp)> sieve = std::priority_queue < Divider, std::vector<Divider>, decltype(cmp)>(cmp);
};

Is there any way I can write this default construction without specifying the type twice? Or just in a cleaner fashion.


Solution

  • Is there any way I can write this default construction without specifying the type twice?

    Yes, you can!

    Use braced-init-list(or uniform-initiation) to initlize the std::priority_queue member of Bar class.

    class Bar
    {
        inline static auto cmp
            = [](const Divider& x, const Divider& y) { return x.next > y.next; };
        std::priority_queue<Divider, std::vector<Divider>, decltype(cmp)> sieve{ cmp };
               //                                                          ^^^^^^^^^^^^^ >> like this
    };
    

    Or simply provide a compare functor, by which you can avoid passing the comparator object to the constructor of the std::priority_queue.

    class Bar
    {
        struct Compare final // compare functor
        {
            bool operator()(const Divider& x, const Divider& y) const { 
                return x.next > y.next;
            }
        };
        std::priority_queue<Divider, std::vector<Divider>, Compare> sieve;
        //                                                 ^^^^^^^^^^^^^^^^^ >> like this
    };