stringtranslate.com

тип объявления

В языке программирования C++ — это ключевое слово, используемое для запроса типа выражения . Представленный в C++11 , он в основном предназначен для использования в универсальном программировании , где часто сложно или даже невозможно выразить типы, которые зависят от параметров шаблона .decltype

Поскольку в 1990-е годы общие методы программирования становились все более популярными, была признана необходимость в механизме вывода типов. Многие поставщики компиляторов реализовали свои собственные версии оператора, обычно называемые typeof, а также были разработаны некоторые переносимые реализации с ограниченной функциональностью, основанные на существующих функциях языка. В 2002 году Бьярн Страуструп предложил добавить стандартизированную версию оператора в язык C++ и предложил имя «decltype», чтобы отразить, что оператор будет возвращать «объявленный тип» выражения.

decltypeСемантика была разработана как для разработчиков универсальных библиотек, так и для начинающих программистов. В общем, выведенный тип соответствует типу объекта или функции точно так, как объявлено в исходном коде. Как и оператор sizeof[1] , decltypeоперанд 's не вычисляется.

Мотивация

С появлением шаблонов в языке программирования C++ и появлением общих методов программирования, впервые предложенных Стандартной библиотекой шаблонов , была признана необходимость в механизме получения типа выражения , обычно называемого . typeofВ обобщенном программировании часто бывает сложно или невозможно выразить типы, которые зависят от параметров шаблона, [2] [3] , в частности, типа возвращаемого значения экземпляров шаблона функции. [2]

Многие поставщики предоставляют typeofоператор как расширение компилятора. [4] Еще в 1997 году, до полной стандартизации C++, Брайан Паркер предложил переносимое решение, основанное на операторе sizeof. [4] Его работа была расширена Биллом Гиббонсом, который пришел к выводу, что эта техника имеет несколько ограничений и, как правило, менее мощна, чем реальный typeofмеханизм. [4] В статье в журнале Dr. Dobb's Journal за октябрь 2000 года Андрей Александреску заметил , что «наличие typeof облегчит написание и понимание кода шаблонов». [5] Он также отметил, что «typeof и sizeof используют один и тот же сервер, потому что sizeof в любом случае должен вычислять тип». [5] Эндрю Кениг и Барбара Э. Му также признали полезность встроенной функции typeof, с оговоркой, что «их использование часто приводит к тонким ошибкам программирования, и есть некоторые проблемы, которые они не могут решить». [6] Они охарактеризовали использование соглашений о типах, таких как определения типов , предоставляемые стандартной библиотекой шаблонов , как более мощный и общий метод. [6] Однако Стив Дьюхерст утверждал, что такие соглашения «дорогостоящие в разработке и распространении», и что было бы «гораздо проще… просто извлечь тип выражения». [7] В статье о C++0x 2011 года Кениг и Му предсказали, что «decltype будет широко использоваться для облегчения написания повседневных программ». [8]

В 2002 году Бьёрн Страуструп предложил расширить язык C++ механизмами запроса типа выражения и инициализации объектов без указания типа. [2] Страуструп заметил, что семантика удаления ссылок, предлагаемая typeofоператором, предоставляемым компиляторами GCC и EDG , может быть проблематичной. [2] И наоборот, оператор, возвращающий ссылочный тип на основе lvalue выражения, считался слишком запутанным. Первоначальное предложение комитету по стандартам C++ предусматривало комбинацию двух вариантов; оператор вернет ссылочный тип только в том случае, если объявленный тип выражения включает ссылку. Чтобы подчеркнуть, что выведенный тип будет отражать «объявленный тип» выражения, оператору было предложено дать имя decltype. [2]

Одним из основных мотивов предложения decltypeбыла возможность писать идеальные шаблоны функций пересылки . [9] Иногда желательно написать универсальную функцию пересылки, которая возвращает тот же тип, что и обернутая функция, независимо от типа, с которым она создана. Без decltype, как правило, это невозможно сделать. [9] Пример, в котором также используется тип Trailing-Return : [9]

интервал и foo ( интервал и я ); поплавок foo ( поплавок & f );    шаблон < класс T > auto Transparent_forwarder ( T & t ) > decltype ( foo ( t )) { return foo ( t ); }          

decltypeздесь важен, поскольку он сохраняет информацию о том, возвращает ли обернутая функция ссылочный тип. [10]

Семантика

Как и в случае с sizeofоператором, операнд decltypeне оценивается, поэтому выражения типа decltype(i++)не приводят к увеличению переменной i. [11] Неформально возвращаемый тип decltype(e)выводится следующим образом: [2]

  1. Если выражение относится к переменной в локальной области или области пространства имен, статической переменной-члену или параметру функции, то результатом будет объявленный типe этой переменной или параметра.
  2. В противном случае, если elvalue ,decltype(e) is T&, где Tтип e; если e является значением x , результат будет T&&; в противном случае e является prvalue и результатом будет T.
  3. В частном случае decltype(auto)допускается вывод типа, autoно при этом сохраняется категория значений инициализатора. Точнее, это эквивалентно .decltype(initializer)

Эта семантика была разработана для удовлетворения потребностей разработчиков универсальных библиотек и в то же время была интуитивно понятной для начинающих программистов, поскольку возвращаемый тип decltypeвсегда соответствует типу объекта или функции точно так, как объявлено в исходном коде. [2] Более формально, Правило 1 применяется к выражениям идентификаторов без скобок и выражениям доступа к членам класса. [12] [13] Пример: [12] Примечание относительно добавленных строк для bar(). Ниже типа, выведенного для "bar()", указан простой int, а не const int, поскольку значения prvalue неклассовых типов всегда имеют неквалифицированные типы cv, несмотря на статически объявленный другой тип.

const int && foo (); константный int бар (); интервал я ; структура А { двойной х ; }; const A * a = новый A (); decltype ( foo ())) x1 ; // тип const int&& decltype ( bar ()) x2 ; // тип int decltype ( i ) x3 ; // тип int decltype ( a -> x ) x4 ; // тип — double decltype (( a -> x )) x5 ; // тип — const double&                         

Причина различия между двумя последними вызовами заключается в decltypeтом, что выражение в скобках (a->x)не является ни выражением идентификатора , ни выражением доступа к члену и, следовательно, не обозначает именованный объект. [14] Поскольку выражение является lvalue, его выведенным типом является «ссылка на тип выражения» или const double&. [11] Тот факт, что дополнительные круглые скобки вводят к типу ссылочный квалификатор, может стать источником ошибок для программистов, которые не до конца понимают decltype. [15]

В декабре 2008 года Яакко Ярви выразил комитету обеспокоенность по поводу невозможности использования decltypeдля формирования квалифицированного-id , [1] что несовместимо с намерением, которое decltype(e)следует рассматривать «как если бы это было typedef-name ». [16] Комментируя официальный проект комитета по C++0x , японский член ISO отметил, что «оператор области видимости (::) не может быть применен к decltype, но его следует применять. В этом случае было бы полезно получить тип члена (вложенный тип) из экземпляра следующим образом: [17]

вектор < интервал > v ; decltype ( v ) :: value_type i = 0 ; // int я = 0;     

Этот и подобные вопросы, касающиеся формулировки, запрещающей использование decltypeв объявлении производного класса и в вызове деструктора , были рассмотрены Дэвидом Вандевурдом и проголосованы за рабочий документ в марте 2010 года. [18] [19]

Доступность

decltypeвключен в стандарт языка C++, начиная с C++11 . [12] Он предоставляется рядом составителей в качестве расширения. Компиляторы Microsoft Visual C++ 2010 и более поздних версий предоставляют decltypeспецификатор типа, который точно имитирует семантику, описанную в предложении комитета по стандартам. Его можно использовать как с управляемым , так и с собственным кодом. [10] В документации говорится, что это «полезно в первую очередь разработчикам, которые пишут библиотеки шаблонов». [10] decltype был добавлен в основную ветку компилятора GCC C++ в версии 4.3, [20] выпущен 5 марта 2008 года. [21] decltype также присутствует в C++ Builder 2009 от Codegear , [22] Intel C++ Compiler , [ 23] и Кланг . [24]

Рекомендации

  1. ^ аб Миллер, Уильям М. (29 сентября 2009 г.). «Активные проблемы стандартного базового языка C++, редакция 66». ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
  2. ^ abcdefg Грегор, Дуглас; Ярви, Яакко; Сик, Джереми; Страуструп, Бьярне (28 апреля 2003 г.). «Decltype и авто» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 28 августа 2015 г.
  3. ^ Калев, Дэнни (08 мая 2008 г.). «Устранение синтаксического беспорядка функции с помощью decltype». DevX.com . Проверено 4 сентября 2009 г.
  4. ^ abc Гиббонс, Билл (01 ноября 2000 г.). «Портативный оператор типа «Оператор». Журнал доктора Добба . Проверено 3 сентября 2009 г.
  5. ^ аб Александреску, Андрей (01 октября 2000 г.). «Общее <Программирование>: Сопоставления между типами и значениями». Журнал доктора Добба . Проверено 3 сентября 2009 г.
  6. ^ Аб Кениг, Эндрю; Барбара Э. Му (1 февраля 2002 г.). «С++ стало проще: именование неизвестных типов». Журнал доктора Добба . Проверено 3 сентября 2009 г.
  7. ^ Дьюхерст, Стив (1 августа 2000 г.). «Общие знания: оператор побитового типа, часть 1». Журнал доктора Добба . Проверено 3 сентября 2009 г.
  8. ^ Кениг, Эндрю; Барбара Э. Му (19 июля 2011 г.). «4 полезных новых функции в C++0x». Журнал доктора Добба . Проверено 12 января 2012 г.
  9. ^ abc Дос Рейс, Габриэль; Ярви, Яакко; Страуструп, Бьярне (12 октября 2004 г.). «Decltype и auto (редакция 4)» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
  10. ^ abc "Оператор decltype". Корпорация Майкрософт . Проверено 4 сентября 2009 г.
  11. ^ аб Дос Рейс, Габриэль; Ярви, Яакко; Страуструп, Бьярне (18 июля 2007 г.). «Decltype (редакция 7): предлагаемая формулировка» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
  12. ^ abc Беккер, Пит. «Рабочий проект стандарта языка программирования C++» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
  13. ^ Миллер, Уильям М. (3 августа 2009 г.). «Отчеты о дефектах стандартного базового языка C++, редакция 65». ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 15 сентября 2009 г.
  14. ^ Миллер, Уильям М. (3 августа 2009 г.). «Закрытые проблемы стандартного базового языка C++, редакция 65». ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
  15. Мазьер, Давид (июнь 2021 г.). «Категории значений C++ и decltype раскрыты» . Проверено 16 июня 2022 г.
  16. ^ Дос Рейс, Габриэль; Ярви, Яакко; Страуструп, Бьярне (5 ноября 2006 г.). «Decltype (редакция 6): предлагаемая формулировка» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
  17. ^ Миллер, Уильям М. (3 августа 2009 г.). «Состояние комментариев C++ CD1». ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
  18. ^ Миллер, Уильям М. (29 марта 2010 г.). «Отчеты о дефектах стандартного базового языка C++, редакция 69». ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 10 апреля 2010 г.
  19. ^ Вандевурде, Давид (3 февраля 2010 г.). «Основные проблемы 743 и 950: дополнительное использование decltype(...)» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 10 апреля 2010 г.
  20. ^ «Поддержка C++0x в GCC» . Фонд свободного программного обеспечения . 27 августа 2009 г. Проверено 4 сентября 2009 г.
  21. ^ "Серия выпусков GCC 4.3" . Фонд свободного программного обеспечения . 13 августа 2009 г. Проверено 4 сентября 2009 г.
  22. ^ «Спецификатор типа decltype (C++0x)» . Эмбаркадеро Технологии. Архивировано из оригинала 8 июля 2011 г. Проверено 4 сентября 2009 г.
  23. ^ "Стд, Кстд" . Корпорация Интел . Проверено 4 сентября 2009 г.
  24. ^ Грегор, Дуглас (26 января 2011 г.). «Поддержка новых функций C++0x в Clang». Архивировано из оригинала 30 января 2011 г.

Внешние ссылки