Dennis
Dennis

Reputation: 165

How to initialize a class data member which is a std::set with custom comparator

I'm not quite sure what is the correct way to initialize an std set with custom comparator when it is a class data member. The following code give me compilation failure once I add the line to insert list iterator into the set. I'm not sure why.

#include <list>
#include <set>
#include <iterator>

auto pred = [](auto const& v1, auto const& v2) {
                *v1 < *v2;
            };
using LstIter = std::list<int>::iterator;

class MaxStack {
public:
    MaxStack()
        :valLst(),
         valSet(pred)
    {}

    void push(int x) {
        valLst.push_back(x);
        LstIter it = std::prev(valLst.end());

        // this line causes compile failure
        valSet.insert(it);
    }

  private:
    std::list<int> valLst;
    std::set<LstIter, decltype(pred)> valSet;    
};

Now the issue is I forgot to type return in lambda. I cannot believe it is case and I have been looking at the code for 10 mins and still didn't see it.

But a more interesting question is then, if that is mistake. Why compiler didn't error out during the class constructor code. while fail when I try to invoke comparator for the first time. shouldn't compiler check the comparator signature when constructing the set?

Upvotes: 1

Views: 544

Answers (2)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

std::set expects its comparator to return a bool. But pred is a void function, it doesn't actually return any value.

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118300

auto pred = [](auto const& v1, auto const& v2) {
                *v1 < *v2;
            };

Fixing this obvious fat-finger to what it should be:

auto pred = [](auto const& v1, auto const& v2) {
                return *v1 < *v2;
            };

Results in gcc 9 successfully compiling the shown code.

Upvotes: 1

Related Questions