简体   繁体   English

正确使用std :: result_of_t

[英]Use std::result_of_t correctly

I'm having this strange problem that I can't wrap my head around. 我有这个奇怪的问题,我无法绕过头脑。 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) seems to say decltype(f) is F&& , I guess (2) and (3) are actually the same. 由于(1)似乎说decltype(f)F&& ,我猜(2)和(3)实际上是相同的。 So, how could decltype(f()) and result_of_t<decltype(f)()> disagree? 那么, decltype(f())result_of_t<decltype(f)()>不同意? And why are decltype(f()) and result_of_t<F&()> the same? 为什么decltype(f())result_of_t<F&()>相同?

For the test(Foo{}) call decltype(f) tells you that f was declared as an rvalue reference type, Foo&& , but that's the type it was declared with, it doesn't tell you what its value category is (ie rvalue or lvalue). 对于test(Foo{})调用decltype(f)告诉你f被声明为rvalue引用类型, Foo&& ,但这是它声明的类型,它不告诉你它的值类别是什么(即rvalue)或左值)。

Within the body of the function f is an lvalue (because it has a name), so decltype(f()) is not the same as result_of_t<F&&()> 在函数体内f是一个左值(因为它有一个名字),所以decltype(f())result_of_t<F&&()>

Consider: 考虑:

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

Here too, f is declared as an rvalue reference type, Foo&& , but that doesn't mean that f() invokes the && -qualified member function. 这里也将f声明为右值引用类型Foo&& ,但这并不意味着f()调用&& -qualified成员函数。 f is an lvalue, so it invokes the & -qualified overload. f是左值,因此它调用& -qualified重载。 To invoke the && -qualified overload you need to use std::move(f)() to make it an rvalue. 要调用&& -qualified重载,您需要使用std::move(f)()使其成为右值。

In your test(F&&) function where you have a universal reference you need to use std::forward to restore the value category of the incoming argument. 在您具有通用引用的test(F&&)函数中,您需要使用std::forward来恢复传入参数的值类别。 To get the same type as result_of_t<decltype(f)()> you need to forward f to restore its original value category, eg 要获得与result_of_t<decltype(f)()>相同的类型,您需要转发f以恢复其原始值类别,例如

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

Now that will have the same type as result_of_t<decltype(f)()> 现在,它将与result_of_t<decltype(f)()>具有相同的类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM