|
#include <cstddef> |
|
#include <functional> |
|
#include <memory> |
|
#include <utility> |
|
#include <stdexcept> |
|
#include <iostream> |
|
|
|
template <typename> |
|
struct shared_function{}; |
|
|
|
/** |
|
* @brief A shared function object that performs shallow copy by default |
|
* @note The operator std::function<...> is intentionally omited so it gets wrapped when passed into a std::function. Allowing the shallow copy capablity to propergate |
|
*/ |
|
template <typename R, typename... Args> |
|
struct shared_function<R(Args...)> |
|
{ |
|
using function_type = std::function<R(Args...)>; |
|
using result_type = R; |
|
|
|
shared_function() = default; |
|
shared_function(const function_type& f) : fptr_(std::make_shared<function_type>(f)) {} |
|
shared_function(function_type&& f) : fptr_(std::make_shared<function_type>(std::move(f))) {} |
|
shared_function(const shared_function<R(Args...)>& other) |
|
{ |
|
fptr_ = other.fptr_; |
|
} |
|
shared_function(shared_function<R(Args...)>&& other) |
|
{ |
|
fptr_ = std::move(other.fptr_); |
|
} |
|
|
|
R operator() (Args... args) |
|
{ |
|
if(!bool(*this)) |
|
throw std::bad_function_call(); |
|
return (*fptr_)((std::forward<Args>(args))...); |
|
} |
|
size_t use_count() const |
|
{ |
|
return fptr_->use_count(); |
|
} |
|
|
|
void reset() |
|
{ |
|
fptr_.reset(); |
|
} |
|
|
|
void swap(shared_function<R(Args...)>& other) const |
|
{ |
|
std::swap(fptr_, other.fptr_); |
|
} |
|
|
|
operator bool() const |
|
{ |
|
return (fptr_ != nullptr) && bool(*fptr_); |
|
} |
|
|
|
protected: |
|
std::shared_ptr<function_type> fptr_; |
|
}; |
|
|
|
template <typename R, typename... Args> |
|
bool operator== (const shared_function<R(Args...)>& func, std::nullptr_t ptr) |
|
{ |
|
return !bool(func); |
|
} |
|
|
|
template <typename R, typename... Args> |
|
bool operator== (std::nullptr_t ptr, const shared_function<R(Args...)>& func) |
|
{ |
|
return !bool(func); |
|
} |
|
|
|
int main() |
|
{ |
|
static_assert(sizeof(shared_function<void(int)>) <= 16, "Static functoin should fit in small function allocation"); |
|
shared_function<void(int)> func([](int n) {std::cout << n << '\n';}); |
|
std::function<void(int)> f(func); |
|
f(1); |
|
} |