我有这个奇怪的问题,我无法绕过头脑.对于此代码:
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
Run Code Online (Sandbox Code Playgroud)
由于(1)似乎说decltype(f)是F&&,我猜(2)和(3)实际上是相同的.那么,怎么可能decltype(f())和result_of_t<decltype(f)()>不同意?为什么decltype(f())和result_of_t<F&()>相同?
因为test(Foo{})调用decltype(f)告诉你f声明为右值引用类型,Foo&&但是它是声明它的类型,它不告诉你它的值类别是什么(即rvalue或lvalue).
在函数体内f是一个左值(因为它有一个名字),所以decltype(f())不一样result_of_t<F&&()>
考虑:
Foo&& f = Foo{};
f();
Run Code Online (Sandbox Code Playgroud)
这里也f被声明为右值引用类型Foo&&,但这并不意味着f()调用&&-qualified成员函数.f是一个左值,所以它调用了&- 限定的重载.要调用&&-qualified重载,您需要使用std::move(f)()它来使其成为右值.
在test(F&&)具有通用引用的函数中,您需要使用它std::forward来恢复传入参数的值类别.要获得相同的类型,result_of_t<decltype(f)()>您需要转发f以恢复其原始值类别,例如
using T1 = decltype(std::forward<F>(f)());
Run Code Online (Sandbox Code Playgroud)
现在它将具有相同的类型 result_of_t<decltype(f)()>
| 归档时间: |
|
| 查看次数: |
1261 次 |
| 最近记录: |