deducing this是C++23引入的语法,将成员函数隐式this参数显式化为带类型占位符的形参,支持对cv/ref限定符进行模板推导;基本形式为在参数列表首位写this auto& self等。

什么是 deducing this(显式对象参数)
这是 C++23 引入的语法,允许把成员函数的第一个隐式 this 参数写成显式的、带类型占位符的形参,从而让编译器能对 this 的 cv/ref 限定(如 const、&&)做模板参数推导。它不是“重载 this”,而是把原本隐式绑定的对象,变成可参与模板推导的普通形参。
怎么写显式对象参数的成员函数
基本形式是:在函数声明中把 this 拿出来,写在参数列表最前面,类型用 auto& 或更精确的 MyClass& 等,支持 const、volatile、引用限定符;若用 auto,就触发推导。
struct Vec {
int x = 0;
// 显式对象参数 + auto → deducing this
void print(this auto& self) {
std::cout << "x = " << self.x << "\n";
}
// 也可限定 const
int get(this const auto& self) const { return self.x; }
// 支持右值限定(注意:this 后面的 && 是函数的引用限定符,不是参数的)
void consume(this Vec&& self) { x = -1; }
};
-
this auto&表示“接受任意 cv/ref 限定的Vec对象,并推导其完整类型” - 不能写
this auto self(必须带引用,因为this总是引用语义) - 显式对象参数必须是第一个参数,且只能有一个
- 仍可有其他普通参数,例如
void set(this auto& self, int v)
它如何改变成员函数重载与设计习惯
以前靠 const/non-const 成员函数重载区分读写权限,现在可以用一个 auto& 函数覆盖多种情况,再用 if constexpr 分支处理逻辑差异——尤其适合通用工具类或需要精细控制 cv/ref 行为的场景。
struct Box {
std::string data;
// 替代 const 和 non-const 两个版本
std::string& get(this auto& self) {
if constexpr (std::is_const_v) {
return const_cast(self.data);
} else {
return self.data;
}
}
};
- 旧写法要定义
const std::string& get() const和std::string& get()两份 - 新写法只需一份,但要注意:返回非常量引用给 const 对象需显式
const_cast,否则编译失败 - 无法替代所有重载:比如想对
Box&&做移动优化,仍需单独写右值引用限定函数(this Box&&),因为auto&不会匹配纯右值 - 显式对象参数函数不参与 ADL(除非显式指定作用域),这点和普通成员函数一致
容易踩的坑和兼容性注意点
这不是“语法糖”,它的行为和传统成员函数有实质差异:对象参数参与模板实例化,可能造成意外的函数模板膨胀,也可能因推导出太具体的类型而失去多态性。
立即学习“C++免费学习笔记(深入)”;
- 不能在虚函数中使用
this auto&—— 虚函数要求签名完全一致,而auto推导后每个调用点生成不同函数,无法构成虚函数重写 - 类模板中使用时,
this auto&推导的是具体特化类型(如Vec),不是模板参数本身,别误以为能直接拿到& T - Clang 15+、GCC 13+、MSVC 19.34+ 支持;C++20 模式下不识别,必须启用
-std=c++23或等效开关 - 调试时栈帧里会显示显式参数名(如
self),而不是隐式的this,部分调试器可能尚未完全适配显示
真正关键的转变在于:你开始把“调用者对象”当作一个可推导、可约束、可 if constexpr 分支的输入,而不是语言强加的隐式上下文。这在写泛型容器适配器或 fluent 接口时特别有用,但也意味着你得更小心地控制推导边界——毕竟,auto 不会自动理解你的设计意图。










