decltype(auto)类型推导:return x vs. return(x)

问题描述 投票:3回答:2

我正在看isocpp.org FAQ on C++14 language extensions,阅读关于decltype(auto)

...

注意:decltype(auto)主要用于推导转发函数和类似包装器的返回类型,如上所示,您希望类型完全“跟踪”您正在调用的某个表达式。但是,除此之外,decltype(auto)并不是一个广泛使用的功能。特别是,尽管它可以用于声明局部变量,但这样做可能只是一个反模式,因为局部变量的引用不应该依赖于初始化表达式。此外,它对您编写return语句的方式很敏感。这两个函数有不同的返回类型:

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str;  }
decltype(auto) look_up_a_string_2() { auto str = lookup1(); return(str); }

第一个返回字符串,第二个返回string &,它是对局部变量str的引用。

我的问题:示例中的返回类型不应该是另一种方式,我的意思是,括号应该形成一个表达式,其类型应该是非引用(或rvalue-reference?);并且没有括号,说str的意思是“左右对str的引用”。我错了吗?

c++ c++14 auto decltype decltype-auto
2个回答
6
投票

是的,括号形成一个表达式。表达式不是引用类型,ever

如果表达式最初具有“对T的引用”类型([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前将类型调整为T.表达式指定由引用表示的对象或函数,表达式是左值或x值,具体取决于表达式。

“对T的引用”表示左值和右值参考。但表达式确实有一个值类别。 str作为一个表达式是左值,(str)也是如此,因为括号保留了类型和值类别。

由于decltype在第二种情况下应用于左值表达式,因此它产生左值引用。

在第一种情况下,id-expressions的特殊恳求规则返回“实体的类型”,这是一种值类型。


2
投票

The FAQ is correct, intuition notwithstanding

(@lubgr指出relevant answer到另一个问题)

语言规范说:

如果参数是对象/函数的未加特征化的名称...则decltype指定此表达式指定的实体的声明类型。

如果参数是T类型的任何其他表达式,那么... b)如果表达式的值类别是lvalue,则decltype指定T&...注意,如果对象的名称是括号,则它变为左值表达式因此,decltype(arg)和decltype((arg))通常是不同的类型。

因此,非括号内的案例是一个例外/特殊情况,显然是为了便于使用decltype(auto)返回引用;没有特殊套管,规则@StoryTeller报价生效:

如果表达式最初具有“对T的引用”类型([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前将类型调整为T.

这会使返回引用变得困难。

绝对与其他魔法定义排在一起,例如元组的破坏顺序或在索引0处具有0的空字符串,具有引用的临时生命周期扩展和其他类似的奇迹......

© www.soinside.com 2019 - 2024. All rights reserved.