Почему декларация исключения catch позволяет скользящие круглые скобки?

Я столкнулся с некоторым кодом на С++, который выглядит следующим образом:

class exception {};

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

Обратите внимание на дополнительный набор круглых скобок в catch (exception()). Согласно Compiler Explorer, он скомпилирован в один и тот же объектный код, как если бы он был написан с помощью catch (exception &).

На каком основании разрешен дополнительный набор круглых скобок и какая часть стандарта позволяет это? Насколько мне известно, предложение catch требует спецификатора типа, но exception() не похоже на спецификатор типа.

Ответ 1

Объявления обработчика исключений работают как декларации функций, в параметрах массива и типа функции настраиваются указатели. (То есть, массивы и функции не могут быть выброшены или пойманы "по значению".) В частности, [except.handle] p2 говорит:

Обработчик типа "массив из T" или тип функции T настраивается как "указатель на T".

Итак, catch (exception()) идентичен catch (exception(*p)()).

Ответ 2

exception() объявляет функцию. Per except#nt:handler, объявление-декларация содержит декларатор. Объявление является типом декларатора. Легко это видеть, потому что exception(int) тоже отлично работает. Обратите внимание, что объявление-исключение происходит точно так же, как объявление параметра, поэтому оно работает точно так же, как объявление функции в параметре.