引言
这是一次在代码中遇到的一个小问题,在网上没有找到解答,遂在解决后分享出来,帮助有同样问题的朋友
直入主题 我们来看一段简单的代码来引入我们的问题
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