Как статический указатель функции бросания на noexcept в С++ 17?

C++17 делает noexcept частью типа функции. Он также допускает неявное преобразование указателей функций noexcept в указатели функций, потенциально вызывающие генерацию.

void (*ptr_to_noexcept)() noexcept = nullptr;
void (*ptr_to_throwing)() = ptr_to_noexcept;  // implicit conversion

http://eel.is/c++draft/expr.static.cast#7 говорит, что static_cast может выполнять обратное преобразование.

void (*noexcept_again)() noexcept = static_cast<void(*)() noexcept>(ptr_to_throwing);

К сожалению, и GCC, и clang говорят мне об обратном: https://godbolt.org/z/TgrL7q

Каков правильный способ сделать это? Являются ли reinterpret_cast и приведение стиля C моими единственными вариантами?


person Filipp    schedule 21.08.2019    source источник
comment
реинтерпретация_cast и приведение в стиле C ‹-- эти два чаще всего являются ошибками. По крайней мере, по мому опыту.   -  person Jesper Juhl    schedule 21.08.2019
comment
Этот вопрос был бы более полезным, если бы он отбросил путаницу по поводу static_cast и просто спросил: «Как я могу разыграть это? В чем опасность?».   -  person Davis Herring    schedule 22.08.2019
comment
Я намеренно не спрашиваю, в чем опасность. Это должно быть не более опасно, чем const_cast, где исходный объект объявлен не const, или приведение от базы к производному, когда я знаю, что моя базовая ссылка на самом деле относится к производному объекту. Меня беспокоит только то, что этот noexcept состав также требует всего риска reinterpret_cast.   -  person Filipp    schedule 23.08.2019


Ответы (1)


Возможно, вы пропустили важную часть:

Инверсия любой стандартной последовательности преобразования, не содержащей lvalue-to-rvalue, массива в указатель, функции в указатель, нулевого указателя, нулевого указателя-члена, логического значения, или указателя на функцию. преобразование, можно выполнить явно с помощью static_cast.

В настоящее время преобразование указателя на функцию включает только преобразование из noexcept в потенциально генерирующее. Поскольку вы выполняете обратное преобразование указателя на функцию, static_cast не будет работать, точно так же, как вы не можете static_cast указать указатель на массив или любое другое из перечисленных здесь преобразований.

Так что да, reinterpret_cast было бы уместно, а также поднимает соответствующие тревожные звоночки, которые должны сопровождаться отказом от noexcept.

person chris    schedule 21.08.2019
comment
Не могли бы вы прокомментировать, почему это ограничение было добавлено к static_cast? - person Filipp; 21.08.2019
comment
@Filipp, у меня нет ничего, кроме предположений, но static_cast старается держаться подальше от более небезопасных вещей и обычно там, когда вам нужно, чтобы значение было другого типа. Я представляю noexcept похожим на const в этом отношении, когда отказ от него нарушает ранее данное обещание, и это может иметь серьезные последствия для читателя. Большинство других инверсий не имеют особого смысла для C++. Меня смутило булево преобразование. Переход от bool к указателю на функцию не имеет большого смысла, но компиляторы разрешают bool для плавающих типов в static_cast. - person chris; 21.08.2019