繁体   English   中英

为不同返回类型的函数返回函数指针的函数

[英]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不是一种类型。 它是一种类型,如classstruct 为了使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM