了解'this'或其他参数是否是右值

问题描述 投票:-1回答:3

假设我们有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);
    }
}

但是这种方法在我的情况下是非常不可取的

提前感谢!

c++ move-semantics rvalue-reference perfect-forwarding
3个回答
4
投票

您可以使用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

到模板参数以将模板约束为所需的参数类型。

至每个


1
投票

这是区分左值this和右值this的方式:


© www.soinside.com 2019 - 2024. All rights reserved.