使用 decltype(auto) 推导出的返回类型是否正确?

LWi*_*sey 13 c++ language-lawyer decltype-auto

decltype(auto) func(int&& n)
{
    return (n);
}
Run Code Online (Sandbox Code Playgroud)

clang 12.0.1接受此代码,但gcc 11.2.1拒绝它:

error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int' 
Run Code Online (Sandbox Code Playgroud)

gcc似乎使用 return type int &&,但带有n内括号,这是正确的吗?

神电演示

Jan*_*tke 2

简短的答案是,decltype(auto)应该推断到int&这里,您发现的是一个GCC 11 错误,该错误似乎已被修复。

\n

对于一个长答案,让我们检查一下占位符类型推导如何适用于decltype(auto)返回类型:

\n
\n

包含占位符类型的类型T和相应的初始化子句 E确定如下:

\n
    \n
  • 如果该return语句没有操作数,E则为void()
  • \n
  • 如果操作数是花括号初始化列表,则程序格式错误。
  • \n
  • 如果操作数是一个X不是赋值表达式的表达式,E则为(X).\n [注 1:逗号表达式 ([expr.comma]) 不是赋值表达式。- 尾注]
  • \n
  • 否则,E是 return 语句的操作数。
  • \n
\n
\n

- [dcl.type.auto.deduct] \xc2\xa72

\n

请注意,我们的表达式(n)是一个赋值表达式1),因此最后一个要点适用,即E = (n)。这是发生的情况E

\n
\n

如果占位符类型说明符的形式为type-constraint opt decltype(auto)T则应单独作为占位符。\n推导的类型按[dcl.type.decltype]T中的描述确定,就好像已是 的操作数一样。Edecltype

\n
\n

- [dcl.type.auto.deduct] \xc2\xa74

\n

这意味着返回类型T是通过以下方式推导的:

\n
using T = decltype(E); // E = (n)\n
Run Code Online (Sandbox Code Playgroud)\n

要确定类型decltype(E)表示什么:

\n
\n

对于表达式E, 表示的类型decltype(E)定义如下:

\n
    \n
  • ifE是一个不带括号的 [...]
  • \n
  • 否则,如果E是 xvalue,decltype(E)则为T&&,其中T是 的类型E
  • \n
  • 否则,如果E是左值,decltype(E)则为T&,其中T是 的类型E
  • \n
  • 否则,decltype(E)是 的类型E
  • \n
\n
\n

- [dcl.type.decltype] \xc2\xa71

\n

n是一个unqualified-id,它是一个左值, 也是(n)。因此,第二个要点适用并decltype(auto)推导出int&

\n
\n

1)与名称相反,赋值表达式不仅仅包含赋值。如果我们足够深入地遵循语法规则,我们最终会得到Primary-Expression,其中包括id-Expression和括号。

\n