#include <utility>
#include <iostream>
#include <functional>
using namespace std;
class Function
{
struct Concept {
typedef Concept * (*cloneFunType)(const Concept *);
cloneFunType m_cloneFun = nullptr;
virtual ~Concept() = default;
};
template<typename F>
struct Model final : Concept {
static Concept* clone(const Concept *c) {
return new Model(static_cast<const Model*>(c)->data);
}
explicit Model(F &&f) : data(move(f)) {
this->m_cloneFun = &Model::clone;
}
explicit Model(const F &f) : data(f) {
this->m_cloneFun = &Model::clone;
}
F data;
};
Concept* object;
public:
~Function() {
delete object;
}
template<typename F>
explicit Function(F&& f)
: object(new Model<typename remove_reference<F>::type>(forward<F>(f)))
{}
Function(Function const& that)
: object((*(that.object->m_cloneFun))(that.object))
{}
Function(Function && that)
: object(that.object)
{
that.object = nullptr;
}
//...
};
struct A {
A() = default;
A(const A&) {
cout << "calling As copy constructor" << endl;
}
A(A&&) {
cout << "calling As move constructor" << endl;
}
};
struct B {
B() = default;
B(const B&) = delete;
B(B&&) {
cout << "calling Bs move constructor" << endl;
}
};
int main(){
auto fA = Function(A()); //at runtime, will only call move constructor.
//auto fB = Function(B()); //will not compile.
cout << "is_copy_constructible<Function>::value: "
<< is_copy_constructible<Function>::value << endl;
cout << "is_copy_constructible<function<void()>>::value: "
<< is_copy_constructible<function<void()>>::value << endl;
}