C++如何使指针指向泛型的对象

引言

这是一次在代码中遇到的一个小问题,在网上没有找到解答,遂在解决后分享出来,帮助有同样问题的朋友

直入主题 我们来看一段简单的代码来引入我们的问题

    template<typename Type>
    struct wrapper_type{
        Type fun;
        ...
    };

首先这是一个简单泛型对象的声明,假如现在有一个需求,就是我们需要一个智能指针指向一个泛型的对象呢?你也许会说,像往常一样不就好了,你也许是这个意思:

    template<typename Type>
    struct wrapper_type{
        Type fun;
        ...
    };
	std::unique_ptr<wrapper_type<Type>> ptr_to_wrapper;

很不幸 错的很离谱,这个Type与上面类的声明中的类型差的很远,甚至作用域也不相同,我们该怎么办呢,解决的方法就是继承:

    struct base_type{
		...
    };
    std::unique_ptr<base_type> ptr;
    template<typename T>
    struct wrapper_type : base_type{
        T fun;
        ...
    };

这样的话我们就可以成功指向了,你也许会说这有什么用呢,举一个比较直观了例子,当我们进行并发编程的时候,我们可能会有一个可调用对象做接口的时候,一般情况下std::function表现良好,但是我们不得不注意到一个事实,就是std::function是可复制可移动的,而我们并发编程中常用的std::packaged_task是可移动不可复制的,这意味着我们要传递一个std::packaged_task的时候我们接口不可以使用std::function,这个时候需要我们自己写一个包装类,以上技巧就派上了用场

class function_wrapper{
    struct base_type{
        virtual void call() = 0;
        virtual ~base_type() {}
    };
    std::unique_ptr<base_type> ptr;
    
    template<typename T>
    struct wrapper_type : base_type{
        T fun;
        wrapper_type(T&& f) : fun(std::move(f)){}
        void call() override {fun();}
    };

    public:
        template<typename T>
        function_wrapper(T&& f) :
            ptr(new wrapper_type<T>(std::move(f))){}
        
        function_wrapper() = default;
        function_wrapper(function_wrapper&& f) : ptr(std::move(f.ptr)){}
        void operator()() {ptr->call();}
        function_wrapper& operator=(function_wrapper&& f){
            ptr = std::move(f.ptr);
            return *this;
        }

        function_wrapper(const function_wrapper&) = delete;
        function_wrapper(function_wrapper&) = delete;
        function_wrapper& operator=(const function_wrapper&) = delete;
};


参考:
C++ concurrency in action

posted @ 2022-07-02 13:18  李兆龙的博客  阅读(74)  评论(0编辑  收藏  举报