Насколько я понимаю, приведение указателей функций к разным типам разрешено стандартом С++ (если они никогда не вызываются):
int my_func(int v) { return v; }
int main() {
using from_type = int(int);
using to_type = void(void);
from_type *from = &my_func;
to_type *to = reinterpret_cast<to_type *>(from);
// ...
}
Более того, если я верну указатель к исходному типу и вызову его, неопределенного поведения не будет.
Все идет нормально. А как насчет следующего?
const bool eq = (to == reinterpret_cast<to_type *>(my_func));
Адрес держится тоже после конвертации, или стандартом это не гарантируется?
Хотя это не имеет отношения к вопросу, возможен сценарий, когда кто-то сильно усердствует со стиранием типа. Если адрес верен, что-то можно сделать, не зная исходного типа функции.
Также ответ на мой вопрос скорее всего "нет", но без спойлеров. Это делает еще более маловероятным повторный вызов. :)
Из [expr.reinterpret.cast].6 (выделено мной):
Указатель функции может быть явно преобразован в указатель функции другого типа. [...]
За исключением того, что преобразование prvalue типа «указатель на T1» в тип «указатель на T2» (где T1 и T2 — типы функций) и обратно на его исходный тип дает исходное значение указателя, результат такого преобразование указателя не указано.
Таким образом, стандарт явно разрешает приведение указателей функций к различным типам FP, а затем обратно. Это исключение из общего правила, согласно которому указатели на функции не указаны.
В моем понимании это означает, что reinterpret_cast
не обязательно должно быть to == reinterpret_cast<to_type *>(my_func)
.
Из-за неуказанного токена. Это имеет смысл, даже если это чертовски неудачно. :(
@skypjack Стандарт, вероятно, намеренно оставляет компилятору большую свободу действий, но я не могу представить ни одной разумной стратегии реализации, в которой он не будет работать. Не думаю, что это имеет какое-то практическое значение. reinterpret_cast
также нельзя использовать в константных выражениях, поэтому их достоверность также не является проблемой.
Я согласен, что трудно увидеть возможное использование, но все же я не хочу полагаться на безопасную политику UB в своем производственном коде. Вы знаете. :)
На самом деле, это не @AdrianMole. Я не спрашиваю здесь о сравнении простых указателей на функции. Я спрашиваю, сохраняется ли адрес после преобразования указателя функции. Сравнительная часть просто для того, чтобы было понятно, что я имею в виду.