C++手写std::function

发布于:2025-04-15 ⋅ 阅读:(24) ⋅ 点赞:(0)
#include <iostream>
#include <memory>
using namespace std;

// 抽象接口类
template <class R, class... Args>
struct ICallable
{
    // 定义通用的函数行为,隐藏真实的类型
    virtual R invoke(Args &&...args) = 0;
    virtual ~ICallable() {};
};

// 包装任意类型桥接类
template <class T, class R, class... Args>
class ICallableImpl : public ICallable<R, Args...>
{
    // 封装任意类型的函数指针
    T callable;

public:
    ICallableImpl(T &&c) : callable(std::move(c)) {};
    R invoke(Args &&...args) override
    {
        return callable(std::forward<Args>(args)...);
    }
};
// 函数指针签名
// void(int)封装
// 类似 using ptr = void(int);
template <class Signature>
class MyFunction;

// 具体实现
template <class R, class... Args>
class MyFunction<R(Args...)>
{
    // 底层是抽象接口智能指针
    std::unique_ptr<ICallable<R, Args...>> funcPtr;

public:
    MyFunction() = default;
    template <class T>
    MyFunction(T &&callable)
    {
        funcPtr = std::make_unique<ICallableImpl<T, R, Args...>>(std::forward<T>(callable));
    }
    // 赋值操作符
    template <class T>
    MyFunction &operator=(T &&callable)
    {
        funcPtr = std::make_unique<ICallableImpl<T, R, Args...>>(std::forward<T>(callable));
        return *this; // 返回 *this 以支持链式赋值
    }
    // 函数调用
    R operator()(Args... args) const
    {
        // 多态
        funcPtr->invoke(std::forward<Args>(args)...);
    }
};

void func()
{
    std::cout << "hello world\n"
              << endl;
}

int add(int a, int b)
{
    return a + b;
}

int main()
{
    // R void
    // Args... ()
    // func class T void()  函数指针
    MyFunction<void()> f1(func);
    f1();
    MyFunction<int(int, int)> f2(add);
    // 3
    int test = f2(1, 2);
    cout << test << endl;
    return 0;
}

为什么需要抽象接口类?

因为如果没有抽象接口类,在写定义时 MyFunction<void()> f1(func);

必须还要写出函数指针,如果把此过程写到构造函数中,让编译器自动推导,方便书写。

一定要注意 函数的三个关键,  type   return,args