-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfunctionwrapper.h
53 lines (45 loc) · 1.67 KB
/
functionwrapper.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
#include <memory>
#include <tuple>
#include <utility>
/**
* previously used a function<void()> as member
* but it cannot use packaged_task since function is copy-constructed
* however packaged_task is move-only, changed it to type-erasure class
*/
class FunctionWrapper {
private:
class ImplBase {
public:
virtual void invoke() = 0;
virtual ~ImplBase() {}
};
std::unique_ptr<ImplBase> impl;
template <typename FunctionType, typename... Args>
class Impl : public ImplBase {
public:
FunctionType f;
std::tuple<Args...> args;
Impl(FunctionType&& f_, Args&&... args_) : f(std::move(f_)), args(std::make_tuple(std::move(args_)...)) {}
void invoke() override {
// expland a tuple as it was a parameter pack
call(std::make_index_sequence<std::tuple_size<std::tuple<Args...>>::value>{});
}
template<std::size_t... Indices>
void call(const std::index_sequence<Indices...>) {
f(std::get<Indices>(std::forward<std::tuple<Args...>>(args))...);
}
};
public:
template <typename F, typename... Args>
FunctionWrapper(F&& f_, Args&&... args_) : impl(new Impl<F, Args...>(std::move(f_), std::move(args_)...)) {}
void operator()() { impl->invoke(); }
FunctionWrapper() = default;
FunctionWrapper(FunctionWrapper&& other) : impl(std::move(other.impl)) {}
FunctionWrapper& operator=(FunctionWrapper&& other) {
impl = std::move(other.impl);
return *this;
}
FunctionWrapper(const FunctionWrapper&) = delete;
FunctionWrapper(FunctionWrapper&) = delete;
FunctionWrapper& operator=(const FunctionWrapper&) = delete;
};