C++显式对象形参
2022年6月20日
字数统计:714
之前的文章C++非静态成员函数的引用限定修饰 提到过C++11为了解决 *this 不区分左右值的问题,引入了引用限定 。其本质原因是 this 作为参数是隐式声明的。而C++23在引用限定 的基础上,大胆的提出了让 this 显式声明的语法,使得 this 不仅可以按左值引用,右值引用传递,甚至还可以以值的方式进行复制传递,同时也使得成员函数内部使用当前对象不再需要使用指针访问运算符。
C++23起,非静态成员函数的声明可以通过在第一个形参前附关键词 this 来指定该形参为显式对象形参:
struct X
{
void foo ( this X const & self , int i ); // 同void foo(int i) const &;
// void foo(int i) const &; // 错误:已经声明
void bar ( this X self , int i ); // 按值传递对象:复制 *this
};
引用限定的版本和附带 this 的版本不能同时存在(实际上就是一个函数),同时附带 this 的版本的内部不再具有 this 指针,需要使用参数名访问当前对象。
对于成员函数模板,显式对象形参的类型和值类别可以被推导,因此该语言特性也被称为“推导 this”:
struct X
{
template < typename Self >
void foo ( this Self && , int );
};
struct D : X {};
void ex ( X & x , D & d )
{
x . foo ( 1 ); // Self = X&
std :: move ( x ). foo ( 2 ); // Self = X
d . foo ( 3 ); // Self = D&
}
这使得成员函数的带 const 限定和不带 const 限定版本只需要一次声明,编译器可根据推导结果选择合适的类外部的函数实现。
此外,显式对象形参会推导成派生类型,因此可以简化CRTP:
// 一个CRTP特性
struct add_postfix_increment
{
template < typename Self >
auto operator ++ ( this Self && self , int )
{
auto tmp = self ; // Self会被推导成some_type
++ self ;
return tmp ;
}
};
struct some_type : add_postfix_increment
{
some_type & operator ++ () { ... }
};
指向有显式对象形参的成员函数的指针是通常的函数指针,而不是到成员的指针:
struct Y
{
int f ( int , int ) const & ;
int g ( this Y const & , int , int );
};
auto pf = & Y :: f ;
pf ( y , 1 , 2 ); // 错误:不能调用指向成员函数的指针
( y . * pf )( 1 , 2 ); // OK
std :: invoke ( pf , y , 1 , 2 ); // OK
auto pg = & Y :: g ;
pg ( y , 3 , 4 ); // OK
( y . * pg )( 3 , 4 ); // 错误:pg不是指向成员函数的指针
std :: invoke ( pg , y , 3 , 4 ); // OK
有显式对象形参的成员函数不能是静态成员函数或虚函数,也不能带有cv或引用限定符。
参考
若无特殊声明,本人原创文章以
CC BY-SA 4.0许可协议
提供。
本站不欢迎非搜索引擎类,非个人学习类爬虫;严禁将文章直接爬取至其他站点。
若看到此条消息,说明你正在访问的网站可能是垃圾二手转载网站。
为了获得更好的浏览体验,请访问唯一原始网站:mysteriouspreserve[dot]com或blog[dot]bizwen[dot]com。