Вывод типа decltype (auto): возврат x против возврата (x) - PullRequest
3 голосов
/ 24 апреля 2019

Я смотрю на isocpp.org FAQ по языковым расширениям C ++ 14 , читая о decltype(auto):

...

Примечание: decltype(auto) в первую очередь полезно для определения возвращаемого типа функций пересылки и аналогичных оболочек, как показано выше, где вы хотите, чтобы тип точно «отслеживал» какое-либо выражение, которое вы вызываете. Тем не менее, decltype (auto) не предназначен для того, чтобы широко использоваться помимо этого. В частности, хотя это можно использовать для объявления локальных переменных, это, вероятно, просто антипаттерн, поскольку ссылка на локальную переменную не должна зависеть от выражения инициализации. Кроме того, он чувствителен к тому, как вы пишете инструкцию возврата. Эти две функции имеют разные типы возврата:

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 означает «lvalue ссылка на str». Я не прав?

Ответы [ 2 ]

6 голосов
/ 24 апреля 2019

Да, скобки образуют выражение. Выражения не относятся к ссылочному типу, ever .

Если выражение изначально имеет тип «ссылка на T» ([dcl.ref], [dcl.init.ref]), тип корректируется до T перед любым дальнейшим анализом. Выражение обозначает объект или функцию, обозначаемую ссылкой, и выражение является lvalue или xvalue, в зависимости от выражения.

«ссылка на T» означает ссылку как на lvalue, так и на rvalue. Но у выражения есть категория значения. str как выражение является lvalue, так же как и (str), так как скобки сохраняют тип и категорию значения.

Поскольку decltype применяется к выражению lvalue во втором случае, он создает ссылку на lvalue.

В первом случае специальное правило запроса для id-выражений возвращает «тип объекта», который является типом значения.

2 голосов
/ 24 апреля 2019

Часто задаваемые вопросы верны, несмотря на интуицию

(@ lubgr указал соответствующий ответ на другой вопрос)

Спецификация языка говорит:

Если аргумент является либо именем объекта / функции, не заключенным в скобки ..., тогда тип decltype определяет объявленный тип объекта, указанный в этом выражении.

Если аргументявляется любым другим выражением типа T, тогда ... b) если категория значения выражения lvalue, тогда decltype указывает T & ... Обратите внимание, что если имя объекта заключено в скобки, оно становится выражением lvalue, таким образом decltype(arg) и decltype ((arg)) часто бывают разных типов.

Таким образом, регистр без скобок является исключительным / специальным случаем, очевидно введенным для облегчения возврата ссылок с помощью decltype (auto);без специального регистра действует правило @StoryTeller в кавычках:

Если выражение изначально имеет тип «ссылка на T» ([dcl.ref], [dcl.init.ref]), тип корректируется до T перед любым дальнейшим анализом.

, и это может затруднить возврат ссылок.

Определенно ранжируется там с другими определениями магии, такими какпорядок уничтожения кортежей или пустых строк, имеющих 0 с индексом 0, временное продление времени жизни со ссылками и другие подобные чудеса ...

...