你知道吗?
C++23 起,可以将自身作为成员函数的首个参数,并通过此参数的类型实现 CV、引用 重载:
示例
struct A{
int id{};
// 旧版成员函数的 cv &/&& 重载写在 ) { 之间
// 新版则通过 this 参数的类型进行重载,因此可用 auto&& 支持所有类型
void print(this auto&& self) { // 函数模板
std::println("A::to_str: {}", self.id);
}
};
// main()
A a{42};
a.print(); // 不需要 self 参数
const A ca{22};
ca.print(); // 能调用 const 版本
甚至可以 this auto self
而非引用,在每次调用时拷贝/移动构造一个新对象。
这并没有额外开销,且许多现代语言也使用这种表示方式。现在 CRTP(奇异递归模板模式)就能这样写:
CRTP
struct Base {
void name(this auto&& self) { self.impl(); }
};
struct D1 : public Base { void impl() { std::puts("D1::impl()"); } };
struct D2 : public Base { void impl() { std::puts("D2::impl()"); } };
旧式的 Base<Derived>
会生成多个 Base
类;而新方式则是一个 Base
类、单例化多个 name
函数。