You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断Base类成员函数中this或参数other是否为rvalue?

嘿,我明白你的困扰——不想用模板友元,又要在成员函数里判断this和other是不是右值对吧?别担心,有几种更合适的方案,我给你详细讲:


方案1:用引用限定符+参数重载,直接区分所有情况

这是最贴合C++设计风格的做法,完全不需要模板友元,靠函数重载就能明确知道this和other的左右值属性:

#include <utility>

class Base {
public:
    // 场景1:调用当前对象是左值,other是左值
    Base doSomething(const Base& other) & {
        // 这里*this是左值,不能随便移动它的资源
        // 按左值逻辑处理即可
        return Base{}; // 示例返回,按需修改
    }

    // 场景2:调用当前对象是左值,other是右值
    Base doSomething(Base&& other) & {
        // other是右值,可以安全移动它的资源
        return std::move(other);
    }

    // 场景3:调用当前对象是右值,other是左值
    Base doSomething(const Base& other) && {
        // *this是右值,放心移动它的资源
        return std::move(*this);
    }

    // 场景4:调用当前对象是右值,other是右值
    Base doSomething(Base&& other) && {
        // 两个都是右值,选一个优先移动就行(看你的业务逻辑)
        return std::move(*this); // 或者std::move(other)
    }

    // 其他成员变量和函数...
};

这种方案的优势是代码逻辑一目了然,每个重载函数对应一种明确的场景,不需要在函数内部做额外判断,而且完全是类的成员函数,不用牵扯友元或者外部模板。


方案2:用内部模板减少重复代码

如果四个重载里有大量重复逻辑,你可以把公共逻辑抽到类内的模板函数里,避免代码复制:

#include <utility>
#include <type_traits>

class Base {
public:
    // 对外暴露的左值调用接口
    Base doSomething(const Base& other) & {
        return doSomethingImpl(other, *this);
    }

    Base doSomething(Base&& other) & {
        return doSomethingImpl(std::move(other), *this);
    }

    // 对外暴露的右值调用接口
    Base doSomething(const Base& other) && {
        return doSomethingImpl(other, std::move(*this));
    }

    Base doSomething(Base&& other) && {
        return doSomethingImpl(std::move(other), std::move(*this));
    }

private:
    // 内部模板实现,用来统一处理所有场景
    template<typename Other, typename Self>
    Base doSomethingImpl(Other&& other, Self&& self) {
        // 编译期判断:当前对象(self)是不是右值
        if constexpr (std::is_rvalue_reference_v<Self&&>) {
            // 处理右值this的逻辑,比如移动资源
            return std::move(self);
        }
        // 编译期判断:other是不是右值
        else if constexpr (std::is_rvalue_reference_v<Other&&>) {
            // 处理右值other的逻辑
            return std::move(other);
        }
        // 两个都是左值的情况
        else {
            return Base{};
        }
    }

    // 其他成员变量和函数...
};

这里用了C++17的if constexpr在编译期做类型判断,没有运行时开销,而且内部模板只在类内可见,完全符合你不想用外部模板友元的要求。


补充说明:为什么不能直接在普通成员函数里判断?

要注意:如果你的成员函数没有加引用限定符(&或&&),不管调用者是左值还是右值,函数内部的*this都会被当成左值,这时候你没法直接判断原对象是不是右值。所以必须用引用限定符来区分调用场景,这是C++标准的规定。

另外,对于other参数,如果它是const Base&类型,你没法直接判断它绑定的是左值还是右值——因为const左值引用可以绑定任何表达式。所以要区分other的左右值,必须给参数做重载:一个用const Base&接收左值,一个用Base&&接收右值,这样在重载函数里就明确知道other的类型了。

内容的提问来源于stack exchange,提问作者defo900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:02:34