簡體   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