![](/img/trans.png)
[英]function pointer for different functions with different data types or parameter
[英]A function that returns a function pointer for functions of different return types
这个问题的背景围绕着硬类型遗传编程。
我想从函数返回一个函数指针,但这些函数指针指向具有不同返回类型的函数。 在另一个堆栈溢出问题( 具有不同返回类型 C 的函数指针)中,建议使用联合的返回类型,但是我正在努力实现。
我对 C++ 相当陌生,所以如果它显示出来,请原谅我的无知。
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
union return_type
{
float(*ffptr)(float, float);
bool(*bfptr)(bool);
};
union fptr(std::string OPERATION) {
if (OPERATION == "Add") {
return_type.ffptr = Add;
} else if (OPERATION == "IfElse") {
return_type.bfptr = IfElse;
}
return return_type;
}
int main() {
std::cout << fptr("Add") << std::endl
return 0;
}
我期望(或者更确切地说是希望)这会打印函数 Add 的地址
TL;DR 版本:我认为您可能正在尝试敲定解决方案以解决问题。 考虑使用诸如访问者模式之类的东西来解耦问题,这样您就不需要知道数据的类型。
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
的一个大问题是知道它们里面有什么。 如果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;
}
但在一天结束时,它仍然不是那么有用。 我认为您可能会发现访问者模式或其一位朋友更有帮助。
你很接近。 注意不要混淆(联合)类型名称的声明和函数返回值。 由于您要引用指针地址,因此我在您的联合 (fpaddr) 中添加了一个 void*,因此您可以清楚地识别出您正在打印一个地址。 请注意,您的 fptr("Add") 返回了联合,并且您需要消除您想要的联合的哪种解释的歧义。
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
//typedef //in C you would use 'typedef'
union fp_return_t
{
float(* ffptr )(float, float);
bool(* bfptr )(bool);
void* fpaddr;
}; //fp_return_t; //in C you would give the name here
fp_return_t fptr(std::string OPERATION) {
fp_return_t fp_return;
if (OPERATION == "Add") {
std::cout << "Add:" << (void*) Add << std::endl;
fp_return.ffptr = Add;
} else if (OPERATION == "IfElse") {
std::cout << "IfElse:" << (void*) IfElse << std::endl;
fp_return.bfptr = IfElse;
}
return fp_return;
}
int main() {
std::cout << fptr("Add").fpaddr << std::endl;
return 0;
}
我不太确定最终目标是什么,但这里是如何使上述编译并打印函数地址(打印Add
的普通Add
以进行比较):
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { return a; }
union return_type
{
float(*ffptr)(float, float);
bool(*bfptr)(bool);
};
union return_type fptr(std::string OPERATION) {
union return_type r;
if (OPERATION == "Add") {
r.ffptr = Add;
} else if (OPERATION == "IfElse") {
r.bfptr = IfElse;
}
return r;
}
int main()
{
/*the void*-cast is technically nonportable but it's hard to
print fn-pointers portably*/
std::cout << reinterpret_cast<void*>(Add) << '\n';
/*you should know which union member is active: */
std::cout << reinterpret_cast<void*>(fptr("Add").ffptr) << '\n';
/*^should be the same address*/
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.