-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbinding.cc
More file actions
98 lines (82 loc) · 2.04 KB
/
binding.cc
File metadata and controls
98 lines (82 loc) · 2.04 KB
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <functional>
#include <iostream>
#include <tuple>
namespace detail
{
template <typename T>
T read(std::istream &in)
{
T val;
in >> val;
return val;
}
template <typename T>
void write(std::ostream &out, T val) { out << val; }
template <typename Fn, typename Tuple, std::size_t ...Is>
decltype(auto) apply_args(Fn fn, const Tuple &tup, std::index_sequence<Is...>)
{
return fn(std::get<Is>(tup)...);
}
}
template <typename ...Args>
struct Creator;
template <>
struct Creator<>
{
static std::tuple<> create_args(std::istream &in)
{
return std::make_tuple();
}
};
template <typename T, typename ...Args>
struct Creator<T, Args...>
{
static std::tuple<T, Args...> create_args(std::istream &in)
{
auto args = Creator<Args...>::create_args(in);
auto arg = std::make_tuple(detail::read<T>(in));
return std::tuple_cat(arg, args);
}
};
template <typename Ret, typename ...Args>
class Proxy
{
public:
explicit Proxy(Ret (*fn)(Args...)) : _fn{fn} {}
void operator()(std::istream &in, std::ostream &out) const
{
auto args = Creator<Args...>::create_args(in);
auto idcs = std::make_index_sequence<sizeof...(Args)>();
auto res = detail::apply_args(_fn, args, idcs);
detail::write(out, res);
}
private:
Ret (*_fn)(Args...);
};
template <typename ...Args>
class Proxy<void, Args...>
{
public:
explicit Proxy(void (*fn)(Args...)) : _fn{fn} {}
void operator()(std::istream &in, std::ostream &out) const
{
auto args = Creator<Args...>::create_args(in);
auto idcs = std::make_index_sequence<sizeof...(Args)>();
detail::apply_args(_fn, args, idcs);
}
private:
void (*_fn)(Args...);
};
template <typename Ret, typename ...Args>
std::function<void(std::istream &, std::ostream &)>
create_proxy(Ret (*fn)(Args...))
{
return Proxy<Ret, Args...>{fn};
}
int test(int i, int j) { return 2 * i + j; }
void noop() {}
int main()
{
create_proxy(test)(std::cin, std::cout);
create_proxy(noop)(std::cin, std::cout);
}