以下所有标准参考均指N4659: March 2017 post-Kona working draft/C++17 DIS。
TLDR:占位符返回类型推导
类是匿名的并不重要,因为返回类型仅从return 语句推导出来。
// Denote the type of the anonymous class as 'T'.
// Return type deduced to 'T'
auto operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
auto& operator[](const char*)
{
return *this;
}
// Return type deduced to 'T&'
decltype(auto) operator[](const char*)
{
return *this;
}
详情及相关标准段落如下。
占位符返回类型推导:auto(C++11 及更高版本)
来自[expr.unary.op]/1 [摘录,强调我的]:
[expr.unary.op]/1 一元* 运算符执行间接:应用它的表达式应该是指向一个
对象类型,或指向函数类型的指针,结果是
左值引用表达式所指向的对象或函数
点。 [...]
因此,*this 的结果是一个左值,指向调用运算符调用的对象。
来自[dcl.spec.auto]/1 和[dcl.spec.auto]/2 [摘录,强调我的]:
[dcl.spec.auto]/1 auto 和 decltype(auto) type-specifiers 用于指定占位符类型 稍后由初始化程序的推导替换。 [...]
[dcl.spec.auto]/2 占位符类型可以与函数声明符一起出现 [...] 在这样的声明符所在的任何上下文中
有效的。 [...] 如果函数声明的返回类型包含一个
占位符类型,函数的返回类型推导自
未丢弃的return 语句 [...]。
来自[dcl.type.auto.deduct]/2 和[dcl.type.auto.deduct]/4 [摘录,强调我的]:
[dcl.type.auto.deduct]/2 包含占位符类型的类型T,以及对应的初始化器e,确定如下:
- (2.1) 用于未丢弃的
return 语句,该语句出现在使用包含占位符类型的返回类型声明的函数中,
T 是声明的返回类型,e 是返回的操作数
陈述。如果 return 语句没有操作数,那么 e 是
void();
- [...]
[dcl.spec.auto]/4如果占位符是自动类型说明符,则推导的类型T'替换T使用规则确定
用于模板参数推导。 [...]
[ 示例:
const auto &i = expr;
i的类型是调用中参数u的推导类型
f(expr) 以下发明的函数模板:
template <class U> void f(const U& u);
— 结束示例 ]
因此,成员运算符函数的返回类型
auto operator[](const char*)
{
return *this;
}
匿名类型,例如T,是以下发明函数模板的调用f(*this) 中参数u 的推导类型:
template <class U> void f(U u);
其中,如上所述,*this 是一个左值,因此推导出返回类型为T;即匿名类的类型。
使用相同的参数,返回成员运算符函数
auto& operator[](const char*)
{
return *this;
}
匿名类型,比如T,是T&。
根据上面的论点,该类是匿名的并不重要,因为返回类型仅从 return 语句推导出来。
占位符返回类型推导:decltype(auto)(C++14 及更高版本)
如果我们将占位符返回类型auto 替换为占位符类型decltype(auto),则不同的规则将控制如何确定返回类型。
decltype(auto) operator[](const char*)
{
return *this;
}
来自[dcl.type.auto.deduct]/5 [摘录,强调我的]:
如果占位符是 decltype(auto) 类型说明符,则 T 应该是单独的占位符。为 T 推导的类型按照 [dcl.type.simple] 中的描述确定,就好像 e 是 decltype 的操作数。
并且,从[dcl.type.simple]/4,[dcl.type.simple]/4.3 适用[提取]:
对于表达式e,decltype(e) 表示的类型定义为
如下:
- [...]
- (4.4) 否则,如果
e 是左值,则decltype(e) 是T&,其中T 是e 的类型;
如上所述,e(return 语句;*this)是左值,[dcl.type.simple]/4.1、[dcl.type.simple]/4.2 和 [dcl.type.simple]/4.3 均不适用于此处。
因此,使用decltype(auto)占位符类型修改的OP示例中的返回类型为T&。