sean-parent Polymorphic Task Template in Ten
#include<memory>
#include<iostream>
#include<utility>
using namespace std;
template<class >
class task;
//...
int main()
{
task<unique_ptr<int>()> f = [_p = make_unique<int>(42)]() mutable
{
return move(_p);
};
cout << *f() << endl;
}
不带small object optimization
#include<memory>
#include<iostream>
#include<utility>
#include<type_traits>
using namespace std;
template<class >
class task;
//...
template<class R, class ... Args>
class task<R(Args...)>
{
struct concept;
template<class F>
struct model;
unique_ptr<concept> _p;
public:
template<class F>
task(F &&f) :
_p(make_unique < model<decay_t<F>> > (forward<F>(f)))
{
}
R operator()(Args ... args)
{
return _p->_invoke(forward<Args>(args)...);
}
};
template<class R, class ... Args>
struct task<R(Args...)>::concept
{
virtual ~concept() = default;
virtual R _invoke(Args&&...) = 0;
};
template<class R, class ... Args>
template<class F>
struct task<R(Args...)>::model final : concept
{
template<class G>
model(G &&f) :
_f(forward<G>(f))
{
}
R _invoke(Args &&... args) override
{
return invoke(_f, forward<Args>(args)…);
}
F _f;
};
带small object optimization
#include<memory>
#include<iostream>
#include<utility>
#include<type_traits>
using namespace std;
template<class >
class task;
/**
* @brief
*
* @tparam R 返回值类型
* @tparam Args 参数类型
*/
template<class R, class ... Args>
class task<R(Args...)>
{
struct concept;
/**
* @tparam F 函数类型
* @tparam Small 是否比buffer小
*/
template<class F, bool Small>
struct model;
/**
* buffer的长度
*/
static constexpr size_t small_size = sizeof(void*) * 4;
/**
* buffer
*/
aligned_storage_t<small_size> _data;
/**
* @brief aliasing,使用void*来作为conversion的bridge
*
* @return
*/
concept& self()
{
return *static_cast<concept*>(static_cast<void*>(&_data));
}
public:
/**
* @brief
*
* @tparam F callable,它可以是function pointer、functor
* @param f
*/
template<class F>
task(F &&f)
{
constexpr bool is_small = sizeof(model<decay_t<F>, true> ) <= small_size;
/**
* placement new
*/
new (&_data) model<decay_t<F>, is_small>(forward<F>(f));
}
~task()
{
/**
* 使用destructor name来调用destructor
*/
self().~concept();
}
task(task &&x) noexcept
{
x.self()._move(&_data);
}
task& operator=(task &&x) noexcept
{
self().~concept();
x.self()._move(&_data);
return *this;
}
R operator()(Args ... args)
{
return self()._invoke(forward<Args>(args)...);
}
};
template<class R, class ... Args>
struct task<R(Args...)>::concept
{
virtual ~concept() = default;
virtual R _invoke(Args&&...) = 0;
virtual void _move(void*) = 0;
};
template<class R, class ... Args>
template<class F>
struct task<R(Args...)>::model<F, true> final : concept
{
template<class G>
model(G &&f) :
_f(forward<G>(f))
{
}
R _invoke(Args &&... args) override
{
return invoke(_f, forward<Args>(args)…);
}
void _move(void *p) override
{
new (p) model(move(*this));
}
F _f;
};
template<class R, class ... Args>
template<class F>
struct task<R(Args...)>::model<F, false> final : concept
{
template<class G>
model(G &&f) :
_p(make_unique<F>(forward<F>(f)))
{
}
R _invoke(Args &&... args) override
{
return invoke(*_p, forward<Args>(args)…);
}
void _move(void *p) override
{
new (p) model(move(*this));
}
unique_ptr<F> _p;
};
1、placement new
new (&_data) model<decay_t<F>, is_small>(forward<F>(f));
完整程序
https://github.com/stlab/libraries/blob/main/stlab/concurrency/task.hpp