-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction_wrapper.h
56 lines (43 loc) · 1.44 KB
/
function_wrapper.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#ifndef FUNCTION_WRAPPER_H
#define FUNCTION_WRAPPER_H
#include <functional>
#include <memory>
#include <type_traits>
class FunctionWrapper {
struct ICallable {
virtual void call() = 0;
virtual ~ICallable() = default;
};
template <typename T>
struct CallableImpl : ICallable {
explicit CallableImpl(T&& f) : callable(std::move(f)) {}
inline void call() override { callable(); }
private:
T callable;
};
std::unique_ptr<ICallable> pImpl;
public:
/*
* perhaps, this implementation can act as type-erased wrapper for
* functions with arguments
* */
template <typename F, typename... Args>
FunctionWrapper(F&& callable, Args&&... args)
: pImpl(std::make_unique<CallableImpl<F>>(
std::move(std::bind(std::forward<F>(callable),
std::forward<Args>(args)...)))){};
template <typename F>
FunctionWrapper(F&& callable)
: pImpl(std::make_unique<CallableImpl<F>>(std::move(callable))){};
// can't be 'default'-ed due to collision with argument-based ctor above
FunctionWrapper(FunctionWrapper&& other) : pImpl(std::move(other.pImpl)) {}
FunctionWrapper& operator=(FunctionWrapper&& other) {
pImpl.swap(other.pImpl);
return *this;
}
FunctionWrapper(const FunctionWrapper&) = delete;
FunctionWrapper& operator=(const FunctionWrapper&) = delete;
~FunctionWrapper() = default;
void operator()() { pImpl->call(); }
};
#endif // FUNCTION_WRAPPER_H