TL; DR версия: я думаю, что вы, возможно, пытаетесь вбить решение в решение проблемы . Рекомендуется использовать что-то вроде Шаблон посетителя , чтобы отделить проблему, чтобы вам не нужно было знать тип данных.
A union
не тип. Это тип типов, например class
или struct
. Чтобы использовать return_type
, вы должны сделать объект, который будет return_type
. Это значит
union fptr(std::string OPERATION) {
if (OPERATION == "Add") {
return_type.ffptr = Add;
} else if (OPERATION == "IfElse") {
return_type.bfptr = IfElse;
}
return return_type;
}
должен выглядеть как
return_type fptr(std::string OPERATION) {
return_type result; // make a return_type object
if (OPERATION == "Add") {
result.ffptr = Add; // set a member of the object
} else if (OPERATION == "IfElse") {
result.bfptr = IfElse;
}
return result; // return the object
}
Тогда вы можете
int main() {
std::cout << fptr("Add").ffptr(10,20) << std::endl; // call the stored function
return 0;
}
Большая проблема с union
s - это знать, что в них. Вы можете безопасно использовать ffptr
, если ffptr
был последним установленным членом.
int main() {
std::cout << fptr("Add").bfptr(true) << std::endl;
return 0;
}
скомпилируется, но при запуске не будет хорошо себя вести. То, что произойдет, не определено, но велика вероятность, что это не будет красиво.
Вы должны быть абсолютно уверены, что функция, сохраненная в объединении, является правильной. Если ваш компилятор обновлен, вы можете использовать std::variant
, чтобы помочь здесь. По крайней мере, он скажет вам, что вы движетесь в неправильном направлении, выдав исключение
#include <iostream>
#include <string>
#include <variant>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
using return_type = std::variant<float (*)(float a, float b), bool (*)(bool a)>;
return_type fptr(std::string OPERATION) {
return_type result;
if (OPERATION == "Add") {
result = Add;
} else if (OPERATION == "IfElse") {
result = IfElse;
}
return result;
}
int main() {
std::cout << std::get<float (*)(float a, float b)>(fptr("Add"))(10,20) << std::endl;
try
{
std::cout << std::get<bool (*)(bool a)>(fptr("Add"))(true) << std::endl;
}
catch (const std::bad_variant_access& e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
Но в конце концов это все же не так уж и полезно. Я думаю, вам может быть полезен шаблон Visitor или один из его друзей.