Проблема в том, что вы используете явные приведения в стиле C. Они общеизвестно опасны.
Здесь в этом случае проблема заключается в том, что fun3
(в отличие от fun2
) уже распадается на указатель функции типа int(*)()
.
Затем вы приведите его к void(*)()
. Это работает, потому что приведение в стиле C будет пытаться выполнять различные выражения приведения C ++, пока одно из них не сработает. В частности, он также попытается reinterpret_cast
.
reinterpret_cast<voidFunctionType>(fun3)
работает, потому что reinterpret_cast
может привести любой указатель функции к любому другому указателю функции.
Однако , вы не можете вызывать функцию через полученный указатель. В результате ваша программа будет иметь неопределенное поведение . Как вы можете видеть, это приведение очень ограничено и опасно, если вы о нем не знаете.
Не используйте приведение в стиле C, используйте вместо него static_cast<voidFunctionType>(fun3)
, и вы получите соответствующую компиляцию ошибка времени в обоих случаях.
Вы не можете использовать функцию (свободную функцию или лямбду), которая возвращает один тип, как если бы он возвратил другой (или нет) тип. Приведение лямбды, которая возвращает int
к void(*)()
, поэтому не имеет смысла.
Если вы действительно хотите сохранить произвольную функцию, указатель на вас можно заставить лямбда-приведение работать, сначала преобразовав его в указатель функции, а затем приведя его к типу указателя функции назначения с reinterpret_cast
. Я бы по-прежнему не использовал приведения в стиле C, потому что reinterpret_cast
по крайней мере прояснит, какой тип приведения вы собираетесь делать:
auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);
Унарный +
- распространенный трюк заставить лямбду к преобразованию указателя на функцию. Обратите также внимание на то, что только лямбда-выражения без перехвата могут быть преобразованы в указатели функций.
Как я объяснил выше, вы должны привести указатель обратно к его первоначальному типу перед вызовом, поэтому вам нужно где-то хранить информацию о типе. Я не уверен, как вы собираетесь это сделать, но вам, вероятно, нужно реализовать какую-то расширенную версию std::function
, см., Например, этот вопрос , как std::function
делает это.