Reputation: 9906
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)>;
Upvotes: 4
Views: 916
Reputation: 170044
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 c++17 or later (for the constexpr lambda). Which also means, we shouldn't be using result_of_t
. But, oh well.
Upvotes: 4
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