一个函数指针模板,向std::function致敬

两年前写这个是因为学C++11练手。而且也因为sizeof(std::function<void()>)的大小有点大,不是指针大小。所以自己写个只有指针大小的版本,不过功能就少很多。

template<typename T> class Caller;//这一句使Caller<void()>这种形式成为可能
template<typename R, typename... AL> class Caller<R(AL...)> final{

    struct Callable{
        virtual ~Callable(){}
        virtual R Call(AL...) = 0;
        virtual Callable *Clone()const = 0;
    }*caller;//这就是用于管理调用对象的指针
    
    //这个模板会根据不同的类型有不同的实例
    template<typename T> class CoreCaller final : public Callable{
        T caller;//T可能是 函数指针、可调用对象、lambda表达式
    public:
        CoreCaller(const T &caller) :caller(caller){}
        R Call(AL... al)final{
            return caller(std::forward<AL>(al)...);
        }
        //必须确保T的类型对象是可复制的,这么设计只是为了便于内存管理,我偷懒了。
        Callable *Clone()const final{
            return new CoreCaller(caller);
        }
    };
    Caller(Callable *caller) :caller(caller){}
public:
    template<typename T> Caller(const T &caller) :
        caller(new CoreCaller<T>(caller)){
    }
    Caller(const Caller &r) :caller(r.caller->Clone()){}
    
    ~Caller(){ delete caller; }
    
    R operator()(AL... al)const{
        return caller->Call(std::forward<AL>(al)...);
    }
    Caller &operator=(const Caller &r){
        if (r.caller == *this)return *this;
        delete caller;
        caller = r.caller->Clone();
        return *this;
    }
};

这样就可以这么用:

void func(){}
class C{
    int operator()(int x){ return x; }
}
Caller<void()> c1(func);//函数指针
c1();
Caller<int(int)> c2(C());//可调用对象
c2(2134);
Caller<void()> c3([](){});//lambda表达式
c3();

基本的思路就是用抽象类Callable提供接口,而模板类CoreCaller根据不同的实例类型实例化。至于Clone,只是我为了让对象可以传递的一种实现,当初本来想用引用计数,那样的话Callable还要添加计数的接口函数,CoreCaller也要多很多计数实现。更重要的是T caller这种写法本身就是拷贝了传进来的对象,考虑到这点干脆就直接用Clone这种解决方案(我承认只是为了偷懒)。

如果想要根据自己的需求定制自己的可调用型智能指针,不妨参考下我的这个实现。

转载于:https://my.oschina.net/chaosannals/blog/668799

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值