Skip to content

Commit 9f5969e

Browse files
committed
wip
1 parent 76baedb commit 9f5969e

13 files changed

+1071
-0
lines changed

format.ps1

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env pwsh
2+
3+
uncrustify -c uncrustify.cfg --no-backup (Get-ChildItem -Recurse include/fet/*.hpp).FullName

include/fet/callable_info.hpp

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#pragma once
2+
3+
#include <tuple>
4+
#include <type_traits>
5+
#include <utility>
6+
7+
namespace fet
8+
{
9+
10+
namespace impl
11+
{
12+
13+
template <class F, class C, class R, class... Arg>
14+
struct CallableInfo
15+
{
16+
using type = F;
17+
18+
using is_function_pointer = std::is_function<std::remove_pointer_t<type>>;
19+
20+
using is_member_function_pointer = std::is_member_function_pointer<type>;
21+
22+
using is_functor = std::is_class<type>;
23+
24+
using class_type = C;
25+
26+
using result_type = R;
27+
28+
using argument_tuple = std::tuple<Arg ...>;
29+
30+
using argument_count = std::tuple_size<argument_tuple>;
31+
32+
template <ssize_t N>
33+
using argument_type = std::tuple_element_t < N<0 ? argument_count::value + N : N, argument_tuple>;
34+
};
35+
36+
template <class F, class R, class... A>
37+
auto getCallableInfo(R (*)(A ...)) -> CallableInfo<F, void, R, A ...>;
38+
39+
template <class F, class C, class R, class... A>
40+
auto getCallableInfo(R (C::*)(A ...))->CallableInfo<F, C, R, A ...>;
41+
42+
template <class F, class C, class R, class... A>
43+
auto getCallableInfo(R (C::*)(A ...) const)->CallableInfo<F, C, R, A ...>;
44+
45+
template <class F>
46+
auto getCallableInfo(F)->decltype(getCallableInfo<F>(&F::operator ()));
47+
48+
template <class F>
49+
using callable_info_t = decltype(impl::getCallableInfo<F>(std::declval<F>()));
50+
51+
} // namespace impl
52+
53+
template <class F>
54+
using callable_info_t = impl::callable_info_t<std::remove_cv_t<std::remove_reference_t<F>>>;
55+
56+
template <ssize_t N, class F>
57+
using argument_t = typename callable_info_t<F>::template argument_type<N>;
58+
59+
} // namespace fet

include/fet/core.hpp

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
#pragma once
2+
3+
#include "util.hpp"
4+
5+
/* ****************************************************************
6+
説明
7+
source : LINQ で言うところの IEnumerable 等
8+
gate : LINQ で言うところの Where, Select 等
9+
drain : LINQ で言うところの ToList, Aggregate 等
10+
11+
書き方: Range, RxCpp と同じようにパイプ演算子使う
12+
auto result = source | gate | gate | ... | drain;
13+
14+
型結合則
15+
source | gate => source
16+
gate | gate => gate
17+
gate | drain => drain
18+
source | drain => decltype(drain.OnComplete())
19+
**************************************************************** */
20+
namespace fet
21+
{
22+
23+
namespace impl
24+
{
25+
26+
template <class T>
27+
struct SourceInfo
28+
{
29+
using value_type = T;
30+
size_t capacity;
31+
};
32+
33+
/* ****************************************************************
34+
std::is_base_of<> の SFINAE によるディスパッチ用タグクラス
35+
それぞれコメント内のメソッドを実装すること
36+
*/
37+
38+
class IJunction
39+
{
40+
// CTX OnConnect(const SourceInfo<E>&) const;
41+
// void OnNext(CTX&, E&&) const;
42+
43+
protected:
44+
template <class T>
45+
constexpr auto OnConnect(const SourceInfo<T>&) const { return nullptr; }
46+
};
47+
48+
class ISource
49+
{
50+
// using value_type;
51+
// SourceInfo<value_type> GetInfo() const;
52+
// CTX Emit(J&&); enable_if J: IJunction
53+
};
54+
55+
class IGate
56+
{
57+
// SourceInfo<T> GetInfo(const SourceInfo<E>&) const;
58+
// CTX OnConnect(const SourceInfo<E>&) const;
59+
// void OnNext(CTX&, E&&, callback) const;
60+
61+
protected:
62+
template <class E>
63+
constexpr auto GetInfo(const SourceInfo<E> &info) const { return info; }
64+
65+
template <class E>
66+
constexpr auto OnConnect(const SourceInfo<E>&) const { return nullptr; }
67+
};
68+
69+
class IDrain: IJunction
70+
{
71+
// CTX OnConnect(const SourceInfo<E>&) const;
72+
// void OnNext(CTX&, E&&) const;
73+
// R OnComplete(CTX&&) const;
74+
75+
protected:
76+
using IJunction::OnConnect;
77+
};
78+
79+
/* ****************************************************************
80+
SFINAE 用 type_traits
81+
gcc4.9 では変数テンプレート使えなくて辛い
82+
C++20 になったら concepts に移行したい
83+
*/
84+
85+
template <class... T>
86+
using is_jct = is_base_of<IJunction, T ...>;
87+
88+
template <class... T>
89+
using is_src = is_base_of<ISource, T ...>;
90+
91+
template <class... T>
92+
using is_gate = is_base_of<IGate, T ...>;
93+
94+
template <class... T>
95+
using is_drain = is_base_of<IDrain, T ...>;
96+
97+
/* ****************************************************************
98+
型結合用クラス
99+
source | gate => source
100+
gate | gate => gate
101+
gate | drain => drain
102+
*/
103+
104+
template <class G, class J, enable_if<is_gate<G>, is_jct<J>> = nullptr>
105+
class Junction: IJunction
106+
{
107+
protected:
108+
G m_gate;
109+
J m_jct;
110+
111+
public:
112+
constexpr Junction(G &&gate, J &&jct):
113+
m_gate (std::forward<G>(gate)),
114+
m_jct (std::forward<J>(jct))
115+
{ }
116+
117+
template <class E>
118+
constexpr auto OnConnect(const SourceInfo<E> &info) const
119+
{
120+
return std::pair<decltype(m_gate.OnConnect(info)), decltype(m_jct.OnConnect(m_gate.GetInfo(info)))> {
121+
m_gate.OnConnect(info), m_jct.OnConnect(m_gate.GetInfo(info))
122+
};
123+
}
124+
125+
template <class CTX, class E>
126+
constexpr auto OnNext(CTX &ctx, E &&e) const
127+
{
128+
return m_gate.OnNext(ctx.first, std::forward<E>(e), [&](auto &&e) {
129+
return m_jct.OnNext(ctx.second, std::forward<decltype(e)>(e));
130+
});
131+
}
132+
};
133+
134+
template <class G, class J, enable_if<is_gate<G>, is_jct<J>> = nullptr>
135+
constexpr Junction<G, J> make_jct(G &&gate, J &&jct)
136+
{
137+
return { std::forward<G>(gate), std::forward<J>(jct) };
138+
}
139+
140+
template <class S, class G, enable_if<is_src<S>, is_gate<G>> = nullptr>
141+
class Source: ISource
142+
{
143+
S m_src;
144+
G m_gate;
145+
146+
public:
147+
constexpr auto GetInfo() const
148+
{
149+
return m_gate.GetInfo(m_src.GetInfo());
150+
}
151+
152+
using value_type = typename decltype(std::declval<Source<S, G>>().GetInfo())::value_type;
153+
154+
constexpr Source(S &&src, G &&gate):
155+
m_src (std::forward<S>(src)),
156+
m_gate (std::forward<G>(gate))
157+
{ }
158+
159+
template <class J, enable_if<is_jct<J>> = nullptr>
160+
constexpr decltype(auto) Emit(J && jct) const & {
161+
return m_src.Emit(make_jct(m_gate, std::forward<J>(jct))).second;
162+
}
163+
164+
template <class J, enable_if<is_jct<J>> = nullptr>
165+
decltype(auto) Emit(J && jct) && {
166+
return std::forward<S>(m_src).Emit(make_jct(std::forward<G>(m_gate), std::forward<J>(jct))).second;
167+
}
168+
};
169+
170+
template <class S, class G, enable_if<is_src<S>, is_gate<G>> = nullptr>
171+
constexpr Source<S, G> make_src(S &&src, G &&gate)
172+
{
173+
return { std::forward<S>(src), std::forward<G>(gate) };
174+
}
175+
176+
template <class G1, class G2, enable_if<is_gate<G1, G2>> = nullptr>
177+
class Gate: IGate
178+
{
179+
G1 m_gate1;
180+
G2 m_gate2;
181+
182+
public:
183+
constexpr Gate(G1 &&gate1, G2 &&gate2):
184+
m_gate1 (std::forward<G1>(gate1)),
185+
m_gate2 (std::forward<G2>(gate2))
186+
{ }
187+
188+
template <class E>
189+
constexpr auto GetInfo(const SourceInfo<E> &info) const
190+
{
191+
return m_gate2.GetInfo(m_gate1.GetInfo(info));
192+
}
193+
194+
template <class E>
195+
constexpr auto OnConnect(const SourceInfo<E> &info) const
196+
{
197+
return std::pair<decltype(m_gate1.OnConnect(info)), decltype(m_gate2.OnConnect(m_gate1.GetInfo(info)))> {
198+
m_gate1.OnConnect(info), m_gate2.OnConnect(m_gate1.GetInfo(info))
199+
};
200+
}
201+
202+
template <class CTX, class E, class CB>
203+
constexpr decltype(auto) OnNext(CTX & ctx, E && e, CB && cb) const {
204+
return m_gate1.OnNext(ctx.first, std::forward<E>(e), [&](auto &&e) {
205+
return m_gate2.OnNext(ctx.second, std::forward<decltype(e)>(e), std::forward<CB>(cb));
206+
});
207+
}
208+
};
209+
210+
template <class G1, class G2, enable_if<is_gate<G1, G2>> = nullptr>
211+
constexpr Gate<G1, G2> make_gate(G1 &&gate1, G2 &&gate2)
212+
{
213+
return { std::forward<G1>(gate1), std::forward<G2>(gate2) };
214+
}
215+
216+
template <class G, class D, enable_if<is_gate<G>, is_drain<D>> = nullptr>
217+
class Drain: IDrain,
218+
Junction<G, D>
219+
{
220+
public:
221+
constexpr Drain(G &&gate, D &&drain):
222+
Junction<G, D>(std::forward<G>(gate), std::forward<D>(drain))
223+
{ }
224+
225+
using Junction<G, D>::OnConnect;
226+
using Junction<G, D>::OnNext;
227+
228+
template <class CTX>
229+
constexpr decltype(auto) OnComplete(CTX && ctx) const & {
230+
return this->m_jct.OnComplete(std::forward<CTX>(ctx).second);
231+
}
232+
233+
template <class CTX>
234+
decltype(auto) OnComplete(CTX && ctx) && {
235+
return std::forward<D>(this->m_jct).OnComplete(std::forward<CTX>(ctx).second);
236+
}
237+
};
238+
239+
template <class G, class D, enable_if<is_gate<G>, is_drain<D>> = nullptr>
240+
constexpr Drain<G, D> make_drain(G &&gate, D &&drain)
241+
{
242+
return { std::forward<G>(gate), std::forward<D>(drain) };
243+
}
244+
245+
/* ****************************************************************
246+
パイプ演算子オーバーロード
247+
source | gate => source
248+
gate | gate => gate
249+
gate | drain => drain
250+
source | drain => decltype(drain.OnComplete())
251+
*/
252+
253+
template <class S, class G, enable_if<is_src<S>, is_gate<G>> = nullptr>
254+
constexpr auto operator |(S &&src, G &&gate)
255+
{
256+
return make_src(std::forward<S>(src), std::forward<G>(gate));
257+
}
258+
259+
template <class G1, class G2, enable_if<is_gate<G1, G2>> = nullptr>
260+
constexpr auto operator |(G1 &&gate1, G2 &&gate2)
261+
{
262+
return make_gate(std::forward<G1>(gate1), std::forward<G2>(gate2));
263+
}
264+
265+
template <class G, class D, enable_if<is_gate<G>, is_drain<D>> = nullptr>
266+
constexpr auto operator |(G &&gate, D &&drain)
267+
{
268+
return make_drain(std::forward<G>(gate), std::forward<D>(drain));
269+
}
270+
271+
template <class S, class D, enable_if<is_src<S>, is_drain<D>> = nullptr>
272+
constexpr decltype(auto) operator |(S && src, D && drain) {
273+
return std::forward<D>(drain).OnComplete(std::forward<S>(src).Emit(drain));
274+
}
275+
276+
} // namespace impl
277+
278+
} // namespace fet

0 commit comments

Comments
 (0)