加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C:非类型函数指针

发布时间:2020-12-16 10:08:00 所属栏目:百科 来源:网络整理
导读:如何在不保存返回类型的情况下保存指向函数的指针? 例如: int GetInt() { return 5; }string GetStr() { return "abc"; }FunctionPointerClass GetAny;int main(){ GetAny = GetInt; auto var = GetAny(); GetAny = GetStr; auto var2 = GetAny(); cout va
如何在不保存返回类型的情况下保存指向函数的指针?
例如:

int GetInt() { return 5; }
string GetStr() { return "abc"; }

FunctionPointerClass GetAny;

int main()
{
    GetAny = &GetInt;
    auto var = GetAny();

    GetAny = &GetStr;
    auto var2 = GetAny();

    cout << var << 'n' << var2;
}

编辑

一种简单的方法是使用变体<> (谢谢@sehe),像这样:

#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>

int         GetInt() { return 5;     }
std::string GetStr() { return "abc"; }

int main()
{
    std::function<boost::variant<int,std::string>()> Get;
    Get = &GetInt;
    std::cout << Get() << 'n';

    Get = &GetStr;
    std::cout << Get() << 'n';
}

但是,它不太适用于我的项目:非类型的类.要使用它,我需要堆叠所有使用的返回类型,将其放在变体<>的模板中.像这样:

class Var {
  private:
    void* _val;

    template <typename T>
    T& _Get() const {
        return *((T*)_val);
    }

    // Static stack variable HERE

  public:
    val() {}

    template <typename T>
    val(T val) {
        Set(val);
    }

    ~val() {
        if(_val != nullptr) delete _val;
    }

    std::function<boost::variant</*Stack*/>()> Get;

    template <typename T>
    void Set(T val) {
        if(_val != nullptr) delete _val;

        _val = new T(val);
        Get = &_Get<T>;

        // TODO Add 'T' to Stack
    }
};

我怎样才能做到这一点?

解决方法

不完全是.

>您当然可以使其成为打印值的功能.
>或者您可以使用std :: variant / boost :: variant返回任一类型.
>其他技术,如Type Erasure也可能适用.

我在这里充实了最后两种方法:

使用变体<>

Live On Coliru

#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>

int         GetInt() { return 5;     }
std::string GetStr() { return "abc"; }

int main()
{
    std::function<boost::variant<int,std::string>()> Get;
    Get = &GetInt;
    std::cout << Get() << 'n';

    Get = &GetStr;
    std::cout << Get() << 'n';
}

打印

5
abc

使用类型擦除

相关技术是类型擦除,您可以使用支持的操作(在本例中为输出流)定义“概念”,并将其隐藏在多态接口后面.例如:

struct Printable {
    template <typename T> Printable(T v) : _stored(new concrete<T>(v)) { }

    friend std::ostream& operator<<(std::ostream& os,Printable const& p) {
        return p._stored->print(os);
    }

  private:
    struct interface {
        virtual std::ostream& print(std::ostream& os) const = 0;
        virtual ~interface() = default;
    };

    template <typename T>
    struct concrete : interface {
        concrete(T v) : v(v) {}
        virtual std::ostream& print(std::ostream& os) const override {
            return os << v;
        }
        T v;
    };

    std::unique_ptr<interface> _stored;
};

在这种情况下,您可以制作整个程序:

Live On Coliru

int         GetInt() { return 5;     }
std::string GetStr() { return "abc"; }

int main()
{
    std::function<Printable()> Get;
    Get = &GetInt;
    std::cout << Get() << 'n';

    Get = &GetStr;
    std::cout << Get() << 'n';
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读