WikiDer > Самый досадный разбор
В самый досадный разбор это особая форма синтаксического разрешение неоднозначности в C ++ язык программирования. Термин использовался Скотт Мейерс в Эффективный STL (2001).[1] Формально это определено в разделе 8.2. Стандарт языка C ++.[2]
Пример с классами
Пример:
учебный класс Таймер { общественный: Таймер();};учебный класс TimeKeeper { общественный: TimeKeeper(const Таймер& т); int get_time();};int главный() { TimeKeeper time_keeper(Таймер()); возвращаться time_keeper.get_time();}Линия
TimeKeeper time_keeper(Таймер());кажется неоднозначным, поскольку его можно интерпретировать либо как
- а Переменная определение переменной
time_keeperклассаTimeKeeper, инициализированный анонимным экземпляром классаТаймерили же - а объявление функции для функции
time_keeperкоторый возвращает объект типаTimeKeeperи имеет единственный (безымянный) параметр, который является указателем на функцию, возвращающую объект типаТаймер(и ничего не предпринимает). (Видеть Функциональный объект # в C и C ++)
Большинство программистов ожидают первого, но Стандарт C ++ требует, чтобы его интерпретировали как второе.
Например, g ++ дает следующее сообщение об ошибке:
$ g ++ -c time_keeper.cctime_keeper.cc: В функции int main ():time_keeper.cc:15: ошибка: запрос члена «get_time» в «time_keeper», который неклассового типа «TimeKeeper (Timer (*) ())»Обратите внимание, что компилятор выдает сообщение об ошибке, касающееся оператора возврата главный(): поскольку он интерпретировал объявление time_keeper в качестве объявления функции мы не сможем вызвать функцию-член get_time () на этом.
Clang ++ дает предупреждение:
$ clang ++ time_keeper.cctimekeeper.cc:14:25: предупреждение: круглые скобки были исключены как объявление функции [-Wvexing-parse] TimeKeeper time_keeper (Таймер ()); ^~~~~~~~~timekeeper.cc:14:26: примечание: добавьте пару круглых скобок для объявления переменной TimeKeeper time_keeper (Timer ()); ^ ( )timekeeper.cc:15:21: ошибка: ссылочный базовый тип TimeKeeper (Timer (*) ()) не является структура или союз вернуть time_keeper.get_time (); ~~~~~~~~~~~^~~~~~~~~
Распространенные способы заставить компилятор рассматривать это как определение переменной:
- Чтобы добавить дополнительную пару круглых скобок:
TimeKeeper time_keeper ((Таймер ())); - Чтобы использовать инициализацию копии:[1]
TimeKeeper time_keeper = TimeKeeper (Таймер ()); - (В C ++ 11 и позже.) Для использования единообразная инициализация[2][3] с подтяжками:
TimeKeeper time_keeper{Таймер ()};TimeKeeper time_keeper (Таймер{});TimeKeeper time_keeper{Таймер{}};
Пример с функциями
Еще более простой пример появляется, когда функциональное приведение предназначено для преобразования выражения для инициализации переменной или передачи в параметр конструктора.
пустота ж(двойной двойной) { int я(int(двойной));}В этом случае круглые скобки вокруг двойной излишни, и объявление я снова является объявлением функции, эквивалентным следующему
// принимает целое число и возвращает целое числоint я(int двойной);Чтобы устранить неоднозначность в пользу объявления переменной, можно использовать тот же метод, что и для первого случая выше. Другое решение - использовать обозначение приведения:
// объявляет переменную с именем 'i'int я((int) двойной);Или также использовать именованное приведение:
// объявляет переменную с именем 'i'int я(static_cast<int>(двойной));Единый синтаксис инициализации
Используя новый единый синтаксис инициализации представленный в C ++ 11 решает эту проблему.
Таким образом, проблемный код становится однозначным при использовании фигурных скобок:
TimeKeeper time_keeper{Таймер{}};Использование фигурных скобок, как указано выше, создает определение переменной для переменной time_keeper класса TimeKeeper, инициализированный анонимным экземпляром класса Таймер.
Рекомендации
- ^ Мейерс, Скотт (2001). Эффективный STL: 50 конкретных способов улучшить использование стандартной библиотеки шаблонов. Эддисон-Уэсли. ISBN 0-201-74962-9.
- ^ ISO/IEC (2003). ISO / IEC 14882: 2003 (E): Языки программирования - C ++ §8.2 Разрешение неоднозначности [dcl.ambig.res]