Функция попробуй поймать синтаксис и основной - PullRequest
16 голосов
/ 06 декабря 2011

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

void foo();

Одно из возможных, законных определений может быть:

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

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

Допустимо ли это для int main()?Например:

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

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

Это законно и хорошо определено?

Ответы [ 2 ]

8 голосов
/ 06 декабря 2011

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

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

Чтениев [исключении. дескриптор] параграфа 13 говорится следующее:

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

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

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

Что касается комментария к OP, вы можете выдать returnоператоры в function-try-block , и [exc.handle] имеет это, чтобы сказать:

Пропускание конца функционального try-блока эквивалентновернуть без значения;это приводит к неопределенному поведению в функции, возвращающей значение (6.6.3).(15.3, пункт 15)

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

0 голосов
/ 06 декабря 2011

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

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