Это неопределенное поведение.
[expr.call] / 1:
Вызов функции через выражение, тип функции которого отличается от типа функции определения вызываемой функции, приводит к неопределенному поведению.
[expr.reinterpret.cast] / 6:
Указатель на функцию может быть явно преобразован в указатель на функцию другого типа. За исключением того, что преобразование значения типа «указатель на T1
» в тип «указатель на T2
» (где T1
и T2
являются типами функций) и обратно в его исходный тип дает исходное значение указателя, Результат такого преобразования указателя не определен.
C ++ вообще не позволяет работать очень большому количеству приведений функций, даже если вы думаете, что это безопасно, например, изменение const
деталей. Когда вам нужна такая вещь, используйте явную функцию-оболочку. Лямбда без захвата может быть одним из простых способов написать ее, не называя ее; или вы можете определить общий шаблон, чтобы обернуть другие функции так, как вам нужно.
[Странно, C ++ 17 допускает неявное преобразование из указателя на функцию, не вызывающую выброса, в указатель на функцию, которая может быть выбрасывающей, даже несмотря на то, что C ++ 17 делает эти различные типы функций - но тогда у меня нет формулировки, которую я могу см. высказывание, что вам действительно разрешено вызывать функцию через этот преобразованный указатель.]