namespace bicycle
{
template<typename Result,typename ...Args>
struct abstract_function
{
virtual Result operator()(Args... args)=0;
virtual abstract_function *clone() const =0;
virtual ~abstract_function() = default;
};
template<typename Func,typename Result,typename ...Args>
class concrete_function: public abstract_function<Result,Args...>
{
Func f;
public:
concrete_function(const Func &x)
: f(x)
{}
Result operator()(Args... args) override
{
return f(args...);
}
concrete_function *clone() const override
{
return new concrete_function{f};
}
};
template<typename Func>
struct func_filter
{
typedef Func type;
};
template<typename Result,typename ...Args>
struct func_filter<Result(Args...)>
{
typedef Result (*type)(Args...);
};
template<typename signature>
class function;
template<typename Result,typename ...Args>
class function<Result(Args...)>
{
abstract_function<Result,Args...> *f;
public:
function()
: f(nullptr)
{}
template<typename Func> function(const Func &x)
: f(new concrete_function<typename func_filter<Func>::type,Result,Args...>(x))
{}
function(const function &rhs)
: f(rhs.f ? rhs.f->clone() : nullptr)
{}
function &operator=(const function &rhs)
{
if( (&rhs != this ) && (rhs.f) )
{
auto *temp = rhs.f->clone();
delete f;
f = temp;
}
return *this;
}
template<typename Func> function &operator=(const Func &x)
{
auto *temp = new concrete_function<typename func_filter<Func>::type,Result,Args...>(x);
delete f;
f = temp;
return *this;
}
Result operator()(Args... args)
{
if(f)
return (*f)(args...);
else
return Result{};
}
~function()
{
delete f;
}
};
}
// ___________________[ Example of usage ]___________________ //
int func1(double)
{
return 1;
}
struct Functor2
{
int operator()(double)
{
return 2;
}
};
double func3(bool,int)
{
return 3.0;
}
struct Functor4
{
double operator()(bool,int)
{
return 4.0;
}
};
int main()
{
int res = 10;
{
bicycle::function<int(double)> f{func1};
res -= f(1.0);
f = Functor2{};
res -= f(2.0);
}
{
bicycle::function<double(bool,int)> f1;
f1 = func3;
bicycle::function<double(bool,int)> f2{f1};
res -= f2(true,1);
f1 = Functor4{};
f2 = f1;
res -= f2(false,2);
}
return res;
}
bmFtZXNwYWNlIGJpY3ljbGUKewogICAgdGVtcGxhdGU8dHlwZW5hbWUgUmVzdWx0LHR5cGVuYW1lIC4uLkFyZ3M+CiAgICBzdHJ1Y3QgYWJzdHJhY3RfZnVuY3Rpb24KICAgIHsKICAgICAgICB2aXJ0dWFsIFJlc3VsdCBvcGVyYXRvcigpKEFyZ3MuLi4gYXJncyk9MDsKICAgICAgICB2aXJ0dWFsIGFic3RyYWN0X2Z1bmN0aW9uICpjbG9uZSgpIGNvbnN0ID0wOwogICAgICAgIHZpcnR1YWwgfmFic3RyYWN0X2Z1bmN0aW9uKCkgPSBkZWZhdWx0OwogICAgfTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jLHR5cGVuYW1lIFJlc3VsdCx0eXBlbmFtZSAuLi5BcmdzPgogICAgY2xhc3MgY29uY3JldGVfZnVuY3Rpb246IHB1YmxpYyBhYnN0cmFjdF9mdW5jdGlvbjxSZXN1bHQsQXJncy4uLj4KICAgIHsKICAgICAgICBGdW5jIGY7CiAgICBwdWJsaWM6CiAgICAgICAgY29uY3JldGVfZnVuY3Rpb24oY29uc3QgRnVuYyAmeCkKICAgICAgICAgICAgOiBmKHgpCiAgICAgICAge30KICAgICAgICBSZXN1bHQgb3BlcmF0b3IoKShBcmdzLi4uIGFyZ3MpIG92ZXJyaWRlCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gZihhcmdzLi4uKTsKICAgICAgICB9CiAgICAgICAgY29uY3JldGVfZnVuY3Rpb24gKmNsb25lKCkgY29uc3Qgb3ZlcnJpZGUKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBuZXcgY29uY3JldGVfZnVuY3Rpb257Zn07CiAgICAgICAgfQogICAgfTsKCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jPgogICAgc3RydWN0IGZ1bmNfZmlsdGVyCiAgICB7CiAgICAgICAgdHlwZWRlZiBGdW5jIHR5cGU7CiAgICB9OwogICAgdGVtcGxhdGU8dHlwZW5hbWUgUmVzdWx0LHR5cGVuYW1lIC4uLkFyZ3M+CiAgICBzdHJ1Y3QgZnVuY19maWx0ZXI8UmVzdWx0KEFyZ3MuLi4pPgogICAgewogICAgICAgIHR5cGVkZWYgUmVzdWx0ICgqdHlwZSkoQXJncy4uLik7CiAgICB9OwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIHNpZ25hdHVyZT4KICAgIGNsYXNzIGZ1bmN0aW9uOwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFJlc3VsdCx0eXBlbmFtZSAuLi5BcmdzPgogICAgY2xhc3MgZnVuY3Rpb248UmVzdWx0KEFyZ3MuLi4pPgogICAgewogICAgICAgIGFic3RyYWN0X2Z1bmN0aW9uPFJlc3VsdCxBcmdzLi4uPiAqZjsKICAgIHB1YmxpYzoKICAgICAgICBmdW5jdGlvbigpCiAgICAgICAgICAgIDogZihudWxscHRyKQogICAgICAgIHt9CiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgRnVuYz4gZnVuY3Rpb24oY29uc3QgRnVuYyAmeCkKICAgICAgICAgICAgOiBmKG5ldyBjb25jcmV0ZV9mdW5jdGlvbjx0eXBlbmFtZSBmdW5jX2ZpbHRlcjxGdW5jPjo6dHlwZSxSZXN1bHQsQXJncy4uLj4oeCkpCiAgICAgICAge30KICAgICAgICBmdW5jdGlvbihjb25zdCBmdW5jdGlvbiAmcmhzKQogICAgICAgICAgICA6IGYocmhzLmYgPyByaHMuZi0+Y2xvbmUoKSA6IG51bGxwdHIpCiAgICAgICAge30KICAgICAgICBmdW5jdGlvbiAmb3BlcmF0b3I9KGNvbnN0IGZ1bmN0aW9uICZyaHMpCiAgICAgICAgewogICAgICAgICAgICBpZiggKCZyaHMgIT0gdGhpcyApICYmIChyaHMuZikgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBhdXRvICp0ZW1wID0gcmhzLmYtPmNsb25lKCk7CiAgICAgICAgICAgICAgICBkZWxldGUgZjsKICAgICAgICAgICAgICAgIGYgPSB0ZW1wOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiAqdGhpczsKICAgICAgICB9CiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgRnVuYz4gZnVuY3Rpb24gJm9wZXJhdG9yPShjb25zdCBGdW5jICZ4KQogICAgICAgIHsKICAgICAgICAgICAgYXV0byAqdGVtcCA9IG5ldyBjb25jcmV0ZV9mdW5jdGlvbjx0eXBlbmFtZSBmdW5jX2ZpbHRlcjxGdW5jPjo6dHlwZSxSZXN1bHQsQXJncy4uLj4oeCk7CiAgICAgICAgICAgIGRlbGV0ZSBmOwogICAgICAgICAgICBmID0gdGVtcDsKICAgICAgICAgICAgcmV0dXJuICp0aGlzOwogICAgICAgIH0KICAgICAgICBSZXN1bHQgb3BlcmF0b3IoKShBcmdzLi4uIGFyZ3MpCiAgICAgICAgewogICAgICAgICAgICBpZihmKQogICAgICAgICAgICAgICAgcmV0dXJuICgqZikoYXJncy4uLik7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHJldHVybiBSZXN1bHR7fTsKICAgICAgICB9CiAgICAgICAgfmZ1bmN0aW9uKCkKICAgICAgICB7CiAgICAgICAgICAgIGRlbGV0ZSBmOwogICAgICAgIH0KICAgIH07Cn0KCi8vIF9fX19fX19fX19fX19fX19fX19bIEV4YW1wbGUgb2YgdXNhZ2UgXV9fX19fX19fX19fX19fX19fX18gLy8KCmludCBmdW5jMShkb3VibGUpCnsKICAgIHJldHVybiAxOwp9CnN0cnVjdCBGdW5jdG9yMgp7CiAgICBpbnQgb3BlcmF0b3IoKShkb3VibGUpCiAgICB7CiAgICAgICAgcmV0dXJuIDI7CiAgICB9Cn07Cgpkb3VibGUgZnVuYzMoYm9vbCxpbnQpCnsKICAgIHJldHVybiAzLjA7Cn0Kc3RydWN0IEZ1bmN0b3I0CnsKICAgIGRvdWJsZSBvcGVyYXRvcigpKGJvb2wsaW50KQogICAgewogICAgICAgIHJldHVybiA0LjA7CiAgICB9Cn07CgppbnQgbWFpbigpCnsKICAgIGludCByZXMgPSAxMDsKICAgIHsKICAgICAgICBiaWN5Y2xlOjpmdW5jdGlvbjxpbnQoZG91YmxlKT4gZntmdW5jMX07CiAgICAgICAgCiAgICAgICAgcmVzIC09IGYoMS4wKTsKICAgICAgICBmID0gRnVuY3RvcjJ7fTsKICAgICAgICByZXMgLT0gZigyLjApOwogICAgfQogICAgewogICAgICAgIGJpY3ljbGU6OmZ1bmN0aW9uPGRvdWJsZShib29sLGludCk+IGYxOwogICAgICAgIGYxID0gZnVuYzM7CgogICAgICAgIGJpY3ljbGU6OmZ1bmN0aW9uPGRvdWJsZShib29sLGludCk+IGYye2YxfTsKICAgICAgICByZXMgLT0gZjIodHJ1ZSwxKTsKCiAgICAgICAgZjEgPSBGdW5jdG9yNHt9OwogICAgICAgIGYyID0gZjE7CiAgICAgICAgcmVzIC09IGYyKGZhbHNlLDIpOwogICAgfQogICAgcmV0dXJuIHJlczsKfQ==