I tried looking at the reflection papers to see if I could remedy this, and I think you could write a macro using token injection such as

consteval std::meta::info overload_set(std::meta::info name) {
    return ^{ [](auto&&... args) -> decltype(auto) {
        return [:\tokens(name):](std::forward<decltype(args)>(args)...);
    } };
}

This could be used as follows:

std::function<void(int)> f = overload_set!(g);

I think it would be much terser than writing out an entire lambda (in this case, a cast would be preferable anyway), and it sidesteps common pitfalls like incurring unnecessary copies by forgetting to perfectly forward the arguments or returning decltype(auto).

I think token reflection is required because it seems that if id-expression denotes an overload set, then ^^id-expression must result in a unique overload to be well-formed, but I'm not an expert on reflection.

Has something like this been proposed or discussed? Of course, you could also do it with C-style macros, but I suspect that would be more controversial.

On Thu, Feb 27, 2025, 4:55 AM Jonathan Wakely <cxx@kayari.org> wrote:


On Thu, 27 Feb 2025, 02:39 Jack O'Donohue via Std-Proposals, <std-proposals@lists.isocpp.org> wrote:
Someone said this could be considered a defect, but it seems more like a proposal to me, especially with pointers to members.

It's not a defect, the original design is working as intended. You're proposing a change to the design.

My main concern is that you don't always use exactly the same signature with the std::function as the target that you construct it with. For example, you might have a function of type const int&(const int&) and want to store it in std::function<long(int)>. Your new constructors wouldn't help here.