c++ - Use std::result_of_t correctly -
i'm having strange problem can't wrap head around. 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); // static_asserts passed test(foo{}); // (1) , (4) passed, (2) , (3) failed since (1) seems decltype(f) f&&, guess (2) , (3) same. so, how decltype(f()) , result_of_t<decltype(f)()> disagree? , why decltype(f()) , result_of_t<f&()> same?
for test(foo{}) call decltype(f) tells f declared rvalue reference type, foo&&, that's type declared with, doesn't tell value category (i.e. rvalue or lvalue).
within body of function f lvalue (because has name), decltype(f()) not same result_of_t<f&&()>
consider:
foo&& f = foo{}; f(); here too, f declared rvalue reference type, foo&&, doesn't mean f() invokes &&-qualified member function. f lvalue, invokes &-qualified overload. invoke &&-qualified overload need use std::move(f)() make rvalue.
in test(f&&) function have universal reference need use std::forward restore value category of incoming argument. same type result_of_t<decltype(f)()> need forward f restore original value category, e.g.
using t1 = decltype(std::forward<f>(f)()); now have same type result_of_t<decltype(f)()>
Comments
Post a Comment