1

Assume I have a class in c++:

struct CompareTuple
{
public:
    auto operator() (const Tuple& t1, const Tuple& t2) -> bool 
    {
        // do comparison and return
    }
};

class Foo 
{
public:
    // some functions
private:
    std::priority_queue<Tuple, std::vector<Tuple>, CompareTuple> heap_;
};

Is this struct CompareTuple is a proper way in modern C++? If it is not, what is a proper way to define a custom compare function in priority queue in modern ways? Because I see, we can use lambda. But I don't know how to define in .h file together with class Foo.

I have tried the example I showed above, it works. But I want to know if it's the best way to do in C++20.

JeJo
  • 30,635
  • 6
  • 49
  • 88
Auzdora
  • 23
  • 4
  • 1
    Personally I would probably create an `bool operator<(Tuple const&, Tuple const&)` overload instead of your function object. – Some programmer dude Jul 31 '23 at 07:53
  • It's fine to use the functor instead of a lambda. A lambda requires a bit less syntactic sugar. In both cases, it's typically a one-shot definition that's specific to the priority queue, and so they should be private and defined within `Foo`. Or, as suggested above you can formalize it by providing built-in ordering directly on `Tuple`. – paddy Jul 31 '23 at 07:55
  • See the examples of the proper ways in the manual https://en.cppreference.com/w/cpp/container/priority_queue, pick one suitable to you. – 273K Jul 31 '23 at 07:57
  • @Someprogrammerdude: Yeah, for some caller side reason, I just have to define a functor instead of overloading < for tuple. This code here is just for demonstration, sry I didn't mention that. – Auzdora Jul 31 '23 at 10:38
  • Please [edit] your question to improve it, and give us more details. Like what is the actual and underlying problem you need to solve? What are your requirements? What are your limitations? Please take some time to read [ask], as well as [how to write the "perfect" question](https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/), especially its [checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – Some programmer dude Jul 31 '23 at 10:42

1 Answers1

2

You should consider providing the operator< in the Tuple itself, which enables the comparison of Tuples by default. If this is not intended for the caller side, you can choose either to use functors or lambda functions.


Is this struct CompareTuple a proper way in modern C++?

Functors are old but golden tools, which work always everywhere. Therefore, it has still relevance in the modern era (IMO), and nothing to worry about that your code will be outdated if it has been chosen to use.


What is a proper way to define a custom compare function in a priority queue in modern C++? Because I see that we can use lambda [...]

Yes, indeed, you could use lambdas as alternatives. Those are handy tools (Since ), by which one could possibly avoid writing arguably lengthy functors, and the definitions of the unnamed function objects (aka. lambda) in place, where it is (possibly only once) required.

For instance, using generic lambdas from , and the support of default constructible lambda in unevaluated context (since ), one could do:

class Foo
{
private:
    // Using lambda function as a custom comparison
    std::priority_queue<Tuple, std::vector<Tuple>,
        decltype([](const auto& lhs, const auto& rhs) {
        return lhs.mX > rhs.mX; //  define the priority as per!
            }) > heap;
public:
   // .... code
};

See demo in godbolt.org


Prior to C++20, it requires two steps:

class Foo
{
private:
    // Captureless lambda as a custom comparison, stored in a function pointer
    bool(*Compare)(const Tuple&, const Tuple&) = [](const Tuple& lhs, const Tuple& rhs){
        return lhs.mX > rhs.mX; //  define the priority as per!
    };
    std::priority_queue<Tuple, std::vector<Tuple>, decltype(Compare)> heap{Compare};

public:
    // .... code
};
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • The last piece of code is actually invalid until C++20, because of the lambda expression in an unevaluated context. – chrysante Jul 31 '23 at 10:26
  • 1
    I didn't mean to say it's not a good solution, on the contrary! It just seemed confusing to me that the code was right next to the C++14 tag :-) – chrysante Jul 31 '23 at 12:42