Danra
Danra

Reputation: 9906

How to use result_of with const overloaded member function

Is there a way to get result_of to work with const overloaded member functions? The regular way demonstrated in cppreference doesn't work since the address of the overloaded function can't be resolved.

#include <type_traits>

class C {
public:
   auto& f () { return x_; }
   const auto& f() const { return x_; }
private:
   int x_;
};

using FRet = std::result_of_t<decltype(&C::f)(C)>;

Wandbox

Upvotes: 4

Views: 916

Answers (2)

The problem is actually not with std::result_of, for all it's peculiarity. The problem is with applying decltype to an overload set. That's ambiguous for a good reason. If we were to write &C::f in a context where there's an explicit or implciit target type, it would be resolved. But naturally there is no target type when we are trying to deduce stuff.

Don't despair yet, however. What we can do is simply add a layer of indirection. Lift the overload set into a functor, and apply the type trait to that. Applying the recipe will look somewhat like that:

class FRetHelper {
    static constexpr auto lifter = [](auto&& a) -> decltype(auto) {
        return std::forward<decltype(a)>(a).f();
    };

public:
    using FRet = std::result_of_t<decltype(lifter)(C)>;
};

using FRet = FRetHelper::FRet;

Live on Wandbox. Major caveat is that it required or later (for the constexpr lambda). Which also means, we shouldn't be using result_of_t. But, oh well.

Upvotes: 4

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

Do not use result_of in this situation - you will have to manually disambiguate the overload. You can simply use decltype and std::declval:

using FRet = decltype(std::declval<C>().f());

If you want to hit the const overload, use:

using FRet = decltype(std::declval<const C>().f());

Upvotes: 9

Related Questions