Подтвердить что ты не робот

Функция try catch syntax и main

Немного известная, но почти никогда не используемая функция С++ получает объявление:

void foo();

Одно возможное юридическое определение может быть:

void foo() try {
  throw 42;
}
catch(...) {
}

Здесь завершена целая реализация функции внутри пары try/catch, которая, похоже, похожа на разрешение это.

Является ли это законным для int main()? Например:.

int main() try {
  throw 42;
}
catch(...) {
}

Правила для основного, n3290 § 3.6.1 в основном говорят о том, какие аргументы он должен принять и что он возвращает - они, похоже, явно не запрещают это они делают с различными другими странными вещами (например, связями), которые могут возникнуть при попытке попробовать.

Является ли это законным и четко определенным?

4b9b3361

Ответ 1

Стандарт не запрещает его использование в [basic.start.main] и, заставляя все реализации поддерживать не менее int main() {/*...*/ } и int main(int argc, char* argv[]) {/*...*/}, не ограничивает реализацию этих двух объявлений (3.6.1, пункт 2).

Из этого в отдельности было бы по крайней мере, что это законно, хотя, конечно, это касается только функций-деклараций, а не определений функций.

Чтение, [except.handle], пункт 13 гласит следующее:

Исключения, брошенные в деструкторы объектов со статическим хранилищем длительность или в конструкторах объектов пространства имен не пойманы функцией-try-block на main(). (15.3 пункт 13)

В нем упоминается блок функции-try, размещенный на main(), что сильно означает, что такая структура является законной и имеет определенное поведение. Добавление информации о том, что main() является только особым в его имени и типе возвращаемого значения, и что реализации не могут перегружать его, чтобы изменить какое-либо поведение, делает довольно сильный случай, когда он действует обычным образом, за исключением случаев, когда они специально отмечены, например, в выше цитаты. Другими словами, да, это законно и четко определено.

Сообщение в блоге, которое я поставил в первой версии этого ответа, на самом деле хорошо иллюстрирует правила, указанные в приведенном выше блоке, поэтому я сохраняю ссылку на него, хотя он напрямую не обсуждает проблему в вопросе OP.

Что касается комментария к OP, вы можете выдавать операторы return внутри функции-try-block, а [except.handle] имеет это сказать:

Вытекание конца функции-try-block эквивалентно возврату без ценности; это приводит к поведению undefined при возврате значения функции (6.6.3). (15.3 пункт 15)

Если вы находитесь в блоке catch в конце main, вы не собираетесь перетекать через тело функции (в данном случае это будет блок try), поэтому автоматически это правило звонки return 0; при потоке не применяются. Вам нужно вернуть int (возможно, код ошибки), чтобы он не становился undefined.

Ответ 2

Я пробовал это, он компилируется, и он работает как ожидалось. Сложная формулировка, но я не думаю, что она нарушает какие-либо правила. Для ясности (для себя и будущих кодовых мантеннеров) вы также можете перефразировать его как:

int main() 
{
    try {
      throw 42;
    }
    catch( int /*...*/) {
    }
}