正确使用std :: result_of_t

时间:2016-07-12 13:22:35

标签: c++ c++11 c++14

我有这个奇怪的问题,我无法绕过头脑。对于此代码:

   foreach($parameter as $value) {
        print_r($value['name']);
        $m = 0;
        foreach($question as $description) {
            print_r($m . ". " . $description);
            $m++;
        }
    }

由于(1)似乎说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 decltype(f),我猜(2)和(3)实际上是相同的。那么,F&&decltype(f())怎么能不同意?为什么result_of_t<decltype(f)()>decltype(f())相同?

1 个答案:

答案 0 :(得分:8)

对于test(Foo{})来电,decltype(f)告诉您f被声明为右值引用类型Foo&&,但这是与其声明的类型,它并没有告诉你它的价值类别是什么(即价值或左值)。

在函数f的正文中是左值(因为它有一个名称),因此decltype(f())result_of_t<F&&()>

不同

考虑:

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

此处,f被声明为右值引用类型Foo&&,但这并不意味着f()调用&& - 限定成员函数。 f是左值,因此它调用& - 限定的重载。要调用&& - 限定的重载,您需要使用std::move(f)()使其成为右值。

在具有通用引用的test(F&&)函数中,您需要使用std::forward来恢复传入参数的值类别。要获得与result_of_t<decltype(f)()>相同的类型,您需要转发f以恢复其原始值类别,例如

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

现在它的类型与result_of_t<decltype(f)()>

相同