假设我们有Base类及其成员函数Base doSomething(const Base&other)。我想知道如何确定这个或其他对象是否为右值,例如我需要类似的东西
Base Base::doSomething(const Base& other) {
...
if(this_is_rvalue) {
// use resources of *this
}
else if(other_is_rvalue) {
// use resources of other
}
...
}
我知道可能的解决方案是使用模板化的朋友功能:
template<typename T1, typename T2, typename = typename std::enable_if<.....>::type>
friend Base doSomething(T1&& this_, T2&& other) {
...
if(std::is_rvalue_reference<T1&&>::value) {
// use resources of this_
return std::move(this_);
}
else if(std::is_rvalue_reference<T2&&>::value) {
// use resources of other
return std::move(other);
}
}
但是这种方法在我的情况下是非常不可取的
提前感谢!
您可以使用4个重载来做到这一点:
Base Base::doSomething(Base& other) && {
// *this is an rvalue and other is an lvalue
}
Base Base::doSomething(Base&& other) && {
// *this and other are rvalues
}
Base Base::doSomething(Base& other) & {
// *this and other are lvalues
}
Base Base::doSomething(Base&& other) & {
// *this is an lvalue and other is an rvalue
}
如果您希望能够接受const Base
,则可以制作这些模板,并使用SFINAE来确定衰减的模板类型为Base
,例如
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, Base>, bool> = true>
Base Base::doSomething(T& other) && {
// *this is an rvalue and other is an lvalue
}
Base Base::doSomething(Base&& other) && {
// *this and other are rvalues
}
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, Base>, bool> = true>
Base Base::doSomething(T& other) & {
// *this and other are lvalues
}
Base Base::doSomething(Base&& other) & {
// *this is an lvalue and other is an rvalue
}
另一种方法是仅使用两个重载和转发引用。然后,您可以检查参数的类型是否为左值引用,以确定您是否具有左值或右值。当您使用转发引用时,这是可行的,因为如果模板参数的类型是右值,则推导为T&
而不是T
。那会给你代码像
template<typename A, typename B, typename C>
Base Base::doSomething(A&& other1, B&& other2, C&& other3) &
{
// this is always an lvalue in this function
if (std::is_lvalue_reference_v<A>)
// other1 is an lvalue
else
// other1 is a rvalue
if (std::is_lvalue_reference_v<B>)
// other2 is an lvalue
else
// other2 is a rvalue
if (std::is_lvalue_reference_v<C>)
// other3 is an lvalue
else
// other3 is a rvalue
}
template<typename A, typename B, typename C>
Base Base::doSomething(A&& other1, B&& other2, C&& other3) &&
{
// this is always an rvalue in this function
if (std::is_lvalue_reference_v<A>)
// other1 is an lvalue
else
// other1 is a rvalue
if (std::is_lvalue_reference_v<B>)
// other2 is an lvalue
else
// other2 is a rvalue
if (std::is_lvalue_reference_v<C>)
// other3 is an lvalue
else
// other3 is a rvalue
}
然后,如果需要,可以通过添加]来限制模板。
std::enable_if_t<std::is_same_v<std::decay_t<A>, type_for_other1>, std::is_same_v<std::decay_t<B>, type_for_other2>, std::is_same_v<std::decay_t<B>, type_for_other3>, bool> = true
到模板参数以将模板约束为所需的参数类型。
至每个
这是区分左值this
和右值this
的方式: