0

Stateless lambdas can be converted to function pointers, e.g. this is valid,

using Fun = bool(*)(int, int);
constexpr auto less = [](int a, int b){ return a < b; };
Fun f{less};

but objects like std::less<int>{} can't.

I do understand why std::less<>{} can't, because it's operator() is not instantiated until the object is applied to some arguments, so how could it be converted to a Fun, if the decision of what its template argument(s) are is not been taken yet?

But std::less<int>{} seems just the same as the lambda I've written above, no?

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • 1
    Probably no one bothered to add the conversion conversion operator. I don't know if C++23 `static operator()` will be applied to `std::less`, if it does, you'll be able to take its address. – HolyBlackCat Nov 16 '22 at 17:43
  • 1
    A lambda being convertible to a function pointer is something the compiler has to do for us. `std::less` was never given that when C++ was updated. That said, the purpose of a functor is to not need/use a function pointer so it kinds of defeats the purpose. – NathanOliver Nov 16 '22 at 17:47
  • Probably just something nobody noticed. Take part in the standards committee if you want to change things. Write a paper/proposal. – Jesper Juhl Nov 16 '22 at 17:48
  • @NathanOliver, I was thinking of a use case where, in a header, you declare a function taking an ordering predicate on some specific type(s), say `Foo`-`Foo`, for which `operator<` is defined, but also an overload not taking that predicate because it internally (i.e. in the implementation file) defaults it to `std::less<>{}`. I might want to declare that parameter as `bool(*)(Foo, Foo)`, so I don't have to bring in ``. – Enlico Nov 16 '22 at 18:12
  • 1
    @Enlico Normally that's done using a template like: `template void foo(Predicate pred)` You can then do a `static_assert` if you want inside the function if `Predicate` does not match what you expect to give the user a "nicer" compiler diagnostic. – NathanOliver Nov 16 '22 at 18:17
  • 1
    A function pointer is bad because it doesn't accept stateful lambdas. You should either make the functor type a template parameter, or use `std::function`. – HolyBlackCat Nov 16 '22 at 18:38

2 Answers2

2

Stateless lambdas can be converted to function pointers, e.g. this is valid, [...] but objects like std::less<int>{} can't.

"Can't" is the wrong word. After all, a "stateless lambda" is just an object, and it doesn't have any magical rules compared to other objects. A lambda is a class type like any other. It is simply generated by the compiler. You can hand write a type that does anything a lambda does; it'd just take more code.

The ability of stateless lambdas to be converted to function pointers is similarly not magic. Any type can have conversion operators defined for it, allowing them to be implicitly convertible to arbitrary types. For a stateless lambda, the compiler simply generates a conversion operator to a pointer to an appropriate function pointer signature.

std::less<T> could have an operator bool (*)(T const&, T const&)() const overload that returns a pointer to a function that does this comparison. But it doesn't. There's nothing stopping it from doing this, save the fact that the C++ standard doesn't say that the type shall have such an interface.

And this hasn't happened because nobody has proposed it for standardization.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
0

std::less<int> has a non-static member function (operator()) that takes two ints and returns a bool.

This is wrong (as @HolyBlackCat pointed out):

It can be converted to a function pointer bool (*)(const std::less<int> *, const int &, const int &). (or to a pointer to member function)

It can be converted to a pointer to member function: bool (std::less<int>::*)(const int &, const int &) const

If it had been defined as a static member function, then the conversion would to bool (*) (const int &, const int &) would be valid.

Marshall Clow
  • 15,972
  • 2
  • 29
  • 45