тип объявления
На ++ языке программирования C decltype
— ключевое слово, для запроса типа выражения используемое . Представленный в C++11 , он в основном предназначен для использования в универсальном программировании , где часто сложно или даже невозможно выражать типы, зависящие от параметров шаблона .
Поскольку в 1990-е годы общие методы программирования становились все более популярными, была признана необходимость в механизме вывода типов. Многие поставщики компиляторов реализовали свои собственные версии оператора, обычно называемые typeof
и были разработаны некоторые переносимые реализации с ограниченной функциональностью, основанные на существующих функциях языка. В 2002 году Бьярн Страуструп предложил добавить стандартизированную версию оператора в язык C++ и предложил название «decltype», чтобы отразить, что оператор будет возвращать «объявленный тип» выражения.
decltype
Семантика была разработана, чтобы удовлетворить потребности как авторов общих библиотек, так и начинающих программистов. В общем, выведенный тип соответствует типу объекта или функции точно так, как объявлено в исходном коде. Как sizeof
[1] оператор, decltype
операнд не оценивается.
Мотивация
[ редактировать ]С появлением шаблонов в языке программирования 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]
int& foo(int& i);
float foo(float& f);
template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) {
return foo(t);
}
decltype
здесь важен, поскольку он сохраняет информацию о том, возвращает ли обернутая функция ссылочный тип. [10]
Семантика
[ редактировать ]Аналогично sizeof
оператор, операнд decltype
не оценивается, поэтому такие выражения, как decltype(i++)
не приведет к увеличению переменной i. [11] Неформально, тип, возвращаемый decltype(e)
выводится следующим образом: [2]
- Если выражение
e
относится к переменной в локальной области или области имен, статической переменной-члену или параметру функции, тогда результатом является объявленный тип этой переменной или параметра. - В противном случае, если
e
это lvalue ,decltype(e)
являетсяT&
, гдеT
— тип e; если e является значением x , результатT&&
; в противном случае e является prvalue и результатом будетT
. - В качестве частного случая
decltype(auto)
позволяет выводить тип, напримерauto
но он сохраняет категорию значений инициализатора. Более конкретно, это эквивалентноdecltype(initializer)
.
Эта семантика была разработана для удовлетворения потребностей разработчиков универсальных библиотек и в то же время была интуитивно понятной для начинающих программистов, поскольку тип возвращаемого значения decltype
всегда соответствует типу объекта или функции точно так, как указано в исходном коде. [2] Более формально, Правило 1 применяется к выражениям id без скобок и выражениям доступа к членам класса. [12] [13] Пример: [12]
Обратите внимание на добавленные строки для bar(). Ниже типа, выведенного для "bar()", указан простой int, а не const int, поскольку значения prvalue неклассовых типов всегда имеют неквалифицированные типы cv, несмотря на статически объявленный другой тип.
const int&& foo();
const int bar();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1; // type is const int&&
decltype(bar()) x2; // type is int
decltype(i) x3; // type is int
decltype(a->x) x4; // type is double
decltype((a->x)) x5; // type is const double&
Причина различия между двумя последними вызовами decltype
заключается в том, что выражение в скобках (a->x)
не является ни выражением идентификатора , ни выражением доступа к члену и, следовательно, не обозначает именованный объект. [14] Поскольку выражение является lvalue, его выведенным типом является «ссылка на тип выражения», или const double&
. [11] Тот факт, что дополнительные круглые скобки вводят к типу ссылочный квалификатор, может стать источником ошибок для программистов, которые не до конца понимают decltype
. [15]
В декабре 2008 года Яакко Ярви выразил обеспокоенность комитету по поводу невозможности использования decltype
для формирования квалифицированного идентификатора , [1] что противоречит намерению decltype(e)
следует рассматривать «как если бы это было имя typedef ». [16] Комментируя официальный проект комитета по C++0x , японский орган-член ISO отметил, что «оператор области видимости (::) не может быть применен к decltype, но это следует сделать. Было бы полезно в случае получения типа члена (вложенный тип) из экземпляра следующим образом: [17]
vector<int> v;
decltype(v)::value_type i = 0; // int i = 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
также присутствует в Codegear от C++ Builder 2009 , [22] компилятор Intel C++ , [23] и Кланг . [24]
Ссылки
[ редактировать ]- ^ Перейти обратно: а б Миллер, Уильям М. (29 сентября 2009 г.). «Активные проблемы стандартного базового языка C++, редакция 66» . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
- ^ Перейти обратно: а б с д и ж г Грегор, Дуглас; Ярви, Джеймс; Сик, Джереми; Страуструп, Бьярне (28 апреля 2003 г.). «Decltype и авто» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 28 августа 2015 г.
- ^ Калев, Дэнни (8 мая 2008 г.). «Очистка синтаксиса функции с помощью decltype » . DevX.com . Проверено 4 сентября 2009 г.
- ^ Перейти обратно: а б с Гиббонс, Билл (1 ноября 2000 г.). «Портативный оператор типа «Оператор» . Журнал доктора Добба . Проверено 3 сентября 2009 г.
- ^ Перейти обратно: а б Александреску, Андрей (01 октября 2000 г.). «Generic<Programming>: Сопоставления между типами и значениями» . Журнал доктора Добба . Проверено 3 сентября 2009 г.
- ^ Перейти обратно: а б Кениг, Эндрю; Барбара Э. Му (1 февраля 2002 г.). «С++ стал проще: именование неизвестных типов» . Журнал доктора Добба . Проверено 3 сентября 2009 г.
- ^ Дьюхерст, Стив (1 августа 2000 г.). «Общие знания: оператор побитового типа, часть 1» . Журнал доктора Добба . Проверено 3 сентября 2009 г.
- ^ Кениг, Эндрю; Барбара Э. Му (19 июля 2011 г.). «4 полезных новых функции в C++0x» . Доктор Журнал Добба . Проверено 12 января 2012 г.
- ^ Перейти обратно: а б с Дос Рейс, Габриэль; Ярви, Джеймс; Страуструп, Бьярне (12 октября 2004 г.). «Decltype и auto (редакция 4)» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
- ^ Перейти обратно: а б с «Оператор decltype» . Корпорация Майкрософт . Проверено 4 сентября 2009 г.
- ^ Перейти обратно: а б Дос Рейс, Габриэль; Ярви, Джеймс; Страуструп, Бьярне (18 июля 2007 г.). «Decltype (редакция 7): предлагаемая формулировка» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
- ^ Перейти обратно: а б с Беккер, Пит. «Рабочий проект стандарта языка программирования C++» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
- ^ Миллер, Уильям М. (3 августа 2009 г.). «Отчеты о дефектах стандартного базового языка C++, редакция 65» . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 15 сентября 2009 г.
- ^ Миллер, Уильям М. (3 августа 2009 г.). «Закрытые проблемы стандартного базового языка C++, редакция 65» . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 4 сентября 2009 г.
- ^ Мазьер, Давид (июнь 2021 г.). «Категории значений C++ и decltype раскрыты» . Проверено 16 июня 2022 г.
- ^ Дос Рейс, Габриэль; Ярви, Джеймс; Страуструп, Бьярне (5 ноября 2006 г.). «Decltype (редакция 6): предлагаемая формулировка» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
- ^ Миллер, Уильям М. (3 августа 2009 г.). «Состояние комментариев C++ CD1» . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 3 октября 2009 г.
- ^ Миллер, Уильям М. (29 марта 2010 г.). «Отчеты о дефектах стандартного базового языка C++, редакция 69» . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 10 апреля 2010 г.
- ^ Вандевурде, Дэвид (3 февраля 2010 г.). «Основные проблемы 743 и 950: дополнительное использование decltype(...)» (PDF) . ISO/IEC JTC1/SC22/WG21 — Комитет по стандартам C++ . Проверено 10 апреля 2010 г.
- ^ «Поддержка C++0x в GCC» . Фонд свободного программного обеспечения . 27 августа 2009 г. Проверено 4 сентября 2009 г.
- ^ «Серия выпусков GCC 4.3» . Фонд свободного программного обеспечения . 13 августа 2009 г. Проверено 4 сентября 2009 г.
- ^ «Спецификатор типа decltype (C++0x)» . Эмбаркадеро Технологии. Архивировано из оригинала 8 июля 2011 г. Проверено 4 сентября 2009 г.
- ^ "стандартный, Qstd" . Корпорация Интел . Проверено 4 сентября 2009 г.
- ^ Грегор, Дуглас (26 января 2011 г.). «Поддержка новых функций C++0x в Clang» . Архивировано из оригинала 30 января 2011 г.
Внешние ссылки
[ редактировать ]