Ответ 1
С++ 14 добавляет случайный край, где круглые скобки вокруг возвращаемого значения могут изменять семантику. Этот фрагмент кода показывает две объявляемые функции. Единственное различие - это скобки вокруг возвращаемого значения.
int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))
В первом func1
возвращается int
, а во втором func1
возвращает int&
. Разница в семантике напрямую связана с окружающими круглыми скобками.
Спецификатор auto
в его последней форме был введен в С++ 11. В С++ Language Spec он описывается как:
Указывает, что тип объявляемой переменной будет автоматически выведенный из его инициализатора. Для функций указывает, что тип возврата является завершающим возвращаемый тип или будет выведен из его операторов возврата (поскольку С++ 14)
Также С++ 11 представил спецификатор decltype
, который описан в С++ Language Spec:
Проверяет объявленный тип объекта или запрашивает тип возвращаемого выражения. [Надрез] 1. Если аргумент является либо нерасширенным именем объекта/функции, либо является выражением доступа к члену (object.member или pointer- > ), тогда decltype указывает объявленный тип объекта, указанный этим выражением.
Если аргументом является любое другое выражение типа T, то
a), если категория значений выражения равна xvalue, тогда decltype указывает T &&
b), если категория значений выражения равна lvalue, тогда decltype указывает T &
c) в противном случае decltype указывает T
[надрез]
Обратите внимание: если имя объекта заключено в скобки, оно становится выражением lvalue, поэтому decltype (arg) и decltype ((arg)) часто являются разными типами.
В С++ 14 возможность использования decltype(auto)
была разрешена для типов возвращаемых функций. Исходные примеры - это то, где вступает в действие семантическая разница с круглыми скобками. Пересмотр исходных примеров:
int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))
decltype(auto)
позволяет возвращать возвращаемый тип возвращаемой функции из выражения entity/expression в операторе return. В первой версии return var1;
фактически совпадает с возвратом типа decltype(var1)
(a int
типа возврата по правилу 1 выше), а во втором случае return (var1);
он фактически совпадает с decltype((var1))
(an возвращаемый тип по правилу 2b).
Скобки создают тип возвращаемого значения int&
вместо int
, таким образом изменяя семантику. Мораль истории - "Не все круглые скобки на возвращаемом типе созданы равными"