Ben
Ben

Reputation: 9723

LIFT macro that has std::invoke-like behavior?

I want to have a LIFT(F) macro. I can write that easily enough:

#define LIFT(F) \
    [&](auto&&... args) \
    noexcept(noexcept((F)(std::forward<decltype(args)>(args)...))) \
    -> decltype((F)(std::forward<decltype(args)>(args)...)) { \
        return (F)(std::forward<decltype(args)>(args)...); \
    }
    
// Now you can use `LIFT(std::max)` as a function-object.

https://godbolt.org/z/r6bY6P15T

I can similarly write one that calls F as a member function on the first argument:

#define LIFT_MEMFN(F) \
    [&](auto&& self, auto&&... args) \
    noexcept(noexcept(std::forward<decltype(self)>(self).F(std::forward<decltype(args)>(args)...))) \
    -> decltype(std::forward<decltype(self)>(self).F(std::forward<decltype(args)>(args)...)) { \
        return std::forward<decltype(self)>(self).F(std::forward<decltype(args)>(args)...); \
    }

https://godbolt.org/z/1cG5YTY1W

What I would like, and I feel like might be possible with crazy SFINAE tricks but I haven't figured it out, is to write a LIFT(F) that acts like std::invoke, so if it is passed a first argument, a0, first try a0.F(args...) then trying a0->F(args...), then falling back to F(a0, args...). Is this possible?

Upvotes: 0

Views: 149

Answers (0)

Related Questions