Use std :: result_of_t correctly

I have such a strange problem that I can’t wrap my head in it. For this code:

struct Foo { int operator()() const & { return 0; } double operator()() const && { return 0; } }; template<typename F> void test(F&& f) { static_assert<is_same<F&&, decltype(f)>::value, "!"); // (1) // intentionally not forwarding f using T1 = decltype(f()); using T2 = result_of_t<decltype(f)()>; using T3 = result_of_t<F&&()>; using T4 = result_of_t<F&()>; static_assert(is_same<T1, T2>::value, "!"); // (2) static_assert(is_same<T1, T3>::value, "!"); // (3) static_assert(is_same<T1, T4>::value, "!"); // (4) } Foo f; test(f); // all static_asserts passed test(Foo{}); // (1) and (4) passed, (2) and (3) failed 

Since (1) it seems decltype(f) is F&& , I believe that (2) and (3) are actually the same. So how could decltype(f()) and result_of_t<decltype(f)()> disagree? And why is decltype(f()) and result_of_t<F&()> the same?

+5
source share
1 answer

Calling test(Foo{}) decltype(f) indicates that f was declared as the reference type of rvalue, Foo&& , but the type with which it was declared does not tell you what its category of values ​​is (i.e. rvalue or lvalue).

There is an lvalue inside the body of the function f (because it has a name), so decltype(f()) does not match result_of_t<F&&()>

Consider:

 Foo&& f = Foo{}; f(); 

Here, f also declared as the reference type rvalue, Foo&& , but this does not mean that f() calls the && -qualified member function. f is an lvalue, so it causes & -qualified overloading. To call && -qualified overload, you need to use std::move(f)() to make it rvalue.

In your test(F&&) function, where you have a generic reference, you need to use std::forward to restore the category of values ​​of the input argument. To get the same type as result_of_t<decltype(f)()> , you need to forward f to restore its original category of values, for example.

 using T1 = decltype(std::forward<F>(f)()); 

Now this type will have the same type as result_of_t<decltype(f)()>

+8
source

All Articles