1

I want to define a class member std::set with function pointer as key_comp, but compiler report "is not a type".

bool compare(unsigned v1, unsigned v2)
{
    ...
}

std::set<unsigned, decltype(compare)*> GoodSet(compare);

class BadSet{
public:
    ...
    std::set<unsigned, decltype<compare>*> Set2(compare);
};

int main()
{
    BadSet S;
    return 0;
}

GoodSet compiled OK, but GNU C++ report at BadSet: "compare is not a type". My system is windows 10 + WSL 2.0 + ubuntu 20.04.

wuyabiao
  • 13
  • 4
  • Use braces for class member initializer: `std::set*> Set2{compare};` – Igor Tandetnik Mar 15 '21 at 03:43
  • Thanks! Set2{compare} works. But why std::set definition inside class require different syntax? – wuyabiao Mar 15 '21 at 03:51
  • @wuyabiao -- Look closely at your attempt. How do you construct a class member object that requires parameters using parentheses (not curly brackets)? You would need to use the member initialization list. Also note that you would have the same issue if you had `struct B { B(int) {} };` and tried to have `B` as a class member of `BadSet`. So the problem has nothing to do with `std::set`. – PaulMcKenzie Mar 15 '21 at 04:02

1 Answers1

1

You can't pass parameters to a member's constructor using parenthesis from inside the parent class declaration, like you are trying to do. You need to either

  • use the member initialization list of the parent class's constructor:
class BadSet{
public:
    ...
    std::set<unsigned, decltype<compare>*> Set2;
    BadSet() : Set2(compare) {}
    ...
};
using myset = std::set<unsigned, decltype<compare>*>;

class BadSet{
public:
    ...
    myset Set2 = myset{compare};
    or
    myset Set2 = myset(compare);
    ...
};
  • or a brace initializer:
class BadSet{
public:
    ...
    std::set<unsigned, decltype<compare>*> Set2{compare};
    ...
};

See Non-static data members for more details.

Also see Using custom std::set comparator

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770