Тема обсуждалась раньше , но это не дубликат.
Когда кто-то спрашивает о разнице между decltype(a)
и decltype((a))
, обычный ответ - a
это переменная, (a)
это выражение. Я считаю этот ответ неудовлетворительным.
Во-первых, a
это также выражение. Варианты основного выражения включают, среди прочего:
- (выражение)
- ID-выражение
Что еще более важно, формулировка для decltype рассматривает скобки очень и очень явно :
For an expression e, the type denoted by decltype(e) is defined as follows:
(1.1) if e is an unparenthesized id-expression naming a structured binding, ...
(1.2) otherwise, if e is an unparenthesized id-expression naming a non-type template-parameter, ...
(1.3) otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, ...
(1.4) otherwise, ...
Так что вопрос остается. Почему скобки обрабатываются по-разному? Кто-нибудь знаком с техническими документами или обсуждениями в комитете? Явное рассмотрение скобок заставляет думать, что это не упущение, поэтому должна быть техническая причина, по которой я скучаю.
c++
c++11
language-lawyer
decltype
Офек Шилон
источник
источник
(a)
- это выражение, аa
также выражение и переменная».Ответы:
Это не недосмотр. Интересно, что в Decltype и auto (revision 4) (N1705 = 04-0145) есть утверждение:
Но в Decltype (редакция 6): предлагаемая формулировка (N2115 = 06-018) одно из изменений
В формулировке нет никакого смысла, но я полагаю, что это своего рода расширение типа decl с использованием немного другого синтаксиса, иными словами, оно предназначалось для дифференциации этих случаев.
Использование для этого показано в C ++ draft9.2.8.4:
Что действительно интересно, так это то, как это работает с
return
утверждением:Моя Visual Studio 2019 предлагает мне удалить лишние круглые скобки, но на самом деле они превращаются в то,
decltype((i))
какие изменения возвращают значение,int&
которое делает его UB с момента возврата ссылки на локальную переменную.источник
Круглые скобки не обрабатываются по-разному. Это не заключенное в скобки id-выражение, которое обрабатывается по-другому.
При наличии скобок применяются обычные правила для всех выражений. Тип и категория значения извлекаются и кодируются в типе
decltype
.Существует специальное положение, чтобы мы могли легче писать полезный код. При применении
decltype
к имени (членской) переменной мы обычно не хотим какой-либо тип, который представляет свойства переменной, когда рассматривается как выражение. Вместо этого нам нужен только тип, с которым объявлена переменная, без необходимости применять тонну свойств типа, чтобы получить ее. И это именно то, чтоdecltype
указано, чтобы дать нам.Если мы позаботимся о свойствах переменной как выражения, то мы все равно сможем получить ее довольно легко, добавив пару скобок.
источник
int
элементаi
изa
,decltype(a.i)
это вint
то время какdecltype((a.i))
естьint&
(предполагается , чтоa
неconst
)? Так как выражениеa.i
присваивается?a.i
является неконстантным lvalue, поэтому вы получаете неконстантный lvalue ссылочный тип для(a.i)
.&
, xvalues&&
и prvalues не являются ссылочными типами.До C ++ 11 языку нужны инструменты для получения информации двух разных типов :
Из-за характера этой информации, функции должны были быть добавлены на языке (это не может быть сделано в библиотеке). Это означает, что новое ключевое слово (ы). Стандарт мог бы ввести два новых ключевых слова для этого. Например,
exprtype
чтобы получить тип выражения иdecltype
получить тип объявления переменной. Это был бы ясный, счастливый вариант.Однако комитет по стандартизации всегда старался изо всех сил избегать введения новых ключевых слов в язык, чтобы минимизировать поломку старого кода. Обратная совместимость является основной философией языка.
Так с C ++ 11 , мы получили только одно ключевое слово , используемое для двух различных вещей:
decltype
. Различия между этими двумя видами использования заключаются в том, чтобы относиться по-decltype(id-expression)
разному. Это было сознательное решение комитета, (небольшой) компромисс.источник
export
был представлен. Если вы можете иметьexport
(ранее все шаблоны были по умолчанию «экспортированы»), вы можете иметь такие вещи, какdecltype
иconstexpr
. Очевидно, что добавлениеregister
на другом языке было бы проблематичным.