转发引用、引用限定符和模板成员函数
Forwarding references, ref qualifiers and template member functions
取如下成员函数:
struct T {
template <typename X> void f(X&& x) { /* ... */ }
};
在这种情况下,x
是转发引用,因为 &&
用于模板内的函数参数。这符合预期。
现在使用这个函数:
struct T {
template <typename X> void f(X&& x) && { /* ... */ }
};
我希望 this
会得到类似的对待;作为转发参考。因此,我希望下面的程序能够编译并且 运行 就好了:
#include <iostream>
struct T {
template <typename X>
bool operator<(X&& rhs) && {
std::cout << "&&" << std::endl;
return true;
}
};
int main() {
T t;
std::cout << (t < T()) << std::endl;
return 0;
}
但是使用 GCC 4.8.4 和 6.0.1,它不会。相反,我得到以下信息:
rvalue.cpp: In function ‘int main()’:
rvalue.cpp:13:25: error: passing ‘T’ as ‘this’ argument of ‘bool T::operator<(X&&) && [with X = T]’ discards qualifiers [-fpermissive]
std::cout << (t < T()) << std::endl;
this
似乎没有成为转发参考。
这是正确的还是错误的? this
是否应该被视为转发参考?标准的哪一部分规定了这一点?
函数末尾的引用限定符声明 operator<
仅应在 LHS 为临时对象时调用。请记住,运算符可以像任何其他成员函数一样被调用,所以您拥有的是
t.operator<(T())
并且t
不是临时的。
如果我们将您的示例更改为
std::cout << (T() < t) << std::endl;
然后它就可以正常工作了,因为您调用 operator<
的对象是一个临时对象。
这里的两个&&
s`区别对待:
struct T {
template <typename X> void f(X&& x) && { /* ... */ }
};
您说得对,x
是转发参考。但是右边的&&
是对对象实例的限定。在这种情况下,f()
只能在对象实例是右值时调用(可能增加混淆的是第一个 &&
将 x
作为转发引用,但第二个 &&
将隐式对象参数作为右值引用)。即:
T().f(4); // ok
T t;
t.f(4); // error
这与 const
资格的工作方式相同:
struct X { void f(); };
const X cx;
cx.f(); // error
成员 operator<() &&
只能在 rvalue 上调用,所以如下:
t < T()
不会起作用,因为 t
不是 rvalue — 它是 lvalue.
以下应该有效:
std::move(t) < T()
还有这个:
T{} < T{}
请注意,我使用 {}
是因为我更习惯使用它们,而且它们的工作效果并不令人意外。
取如下成员函数:
struct T {
template <typename X> void f(X&& x) { /* ... */ }
};
在这种情况下,x
是转发引用,因为 &&
用于模板内的函数参数。这符合预期。
现在使用这个函数:
struct T {
template <typename X> void f(X&& x) && { /* ... */ }
};
我希望 this
会得到类似的对待;作为转发参考。因此,我希望下面的程序能够编译并且 运行 就好了:
#include <iostream>
struct T {
template <typename X>
bool operator<(X&& rhs) && {
std::cout << "&&" << std::endl;
return true;
}
};
int main() {
T t;
std::cout << (t < T()) << std::endl;
return 0;
}
但是使用 GCC 4.8.4 和 6.0.1,它不会。相反,我得到以下信息:
rvalue.cpp: In function ‘int main()’:
rvalue.cpp:13:25: error: passing ‘T’ as ‘this’ argument of ‘bool T::operator<(X&&) && [with X = T]’ discards qualifiers [-fpermissive]
std::cout << (t < T()) << std::endl;
this
似乎没有成为转发参考。
这是正确的还是错误的? this
是否应该被视为转发参考?标准的哪一部分规定了这一点?
函数末尾的引用限定符声明 operator<
仅应在 LHS 为临时对象时调用。请记住,运算符可以像任何其他成员函数一样被调用,所以您拥有的是
t.operator<(T())
并且t
不是临时的。
如果我们将您的示例更改为
std::cout << (T() < t) << std::endl;
然后它就可以正常工作了,因为您调用 operator<
的对象是一个临时对象。
这里的两个&&
s`区别对待:
struct T {
template <typename X> void f(X&& x) && { /* ... */ }
};
您说得对,x
是转发参考。但是右边的&&
是对对象实例的限定。在这种情况下,f()
只能在对象实例是右值时调用(可能增加混淆的是第一个 &&
将 x
作为转发引用,但第二个 &&
将隐式对象参数作为右值引用)。即:
T().f(4); // ok
T t;
t.f(4); // error
这与 const
资格的工作方式相同:
struct X { void f(); };
const X cx;
cx.f(); // error
成员 operator<() &&
只能在 rvalue 上调用,所以如下:
t < T()
不会起作用,因为 t
不是 rvalue — 它是 lvalue.
以下应该有效:
std::move(t) < T()
还有这个:
T{} < T{}
请注意,我使用 {}
是因为我更习惯使用它们,而且它们的工作效果并不令人意外。