generated from Sigmarik/cpp-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
match_to.hpp
88 lines (69 loc) · 2.19 KB
/
match_to.hpp
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
/**
* @file match_to.hpp
* @author Kudryashov Ilya ([email protected])
* @brief Match<...>::To<...>::From<...> syntax definition
* @version 0.1
* @date 2024-07-23
*
* @copyright Copyright (c) 2024
*
*/
#pragma once
#include <optional>
#include "abstract_holder.hpp"
/**
* @brief Runtime class-to-class map.
* @brief
*
* @tparam Ts
*/
template <class... Ts>
struct Match {
template <class Root, class... Us>
struct To {
template <class... Vs>
struct From {
using Actor = std::function<Root*(Vs... args)>;
template <class Source>
static std::optional<Actor> constructor(const Source* initiator) {
std::size_t match_id = 0;
bool loop1 =
(check_and_iterate<Ts>(initiator, match_id) || ...);
if (!loop1) return {};
Actor result;
std::size_t output_iterator = 0;
bool loop2 =
(count_and_iterate<Us>(result, match_id, output_iterator) ||
...);
assert(loop2);
return result;
}
private:
template <class CurrentClass, class Source>
static bool check_and_iterate(const Source* initiator,
std::size_t& iterator) {
if (!dynamic_cast<const CurrentClass*>(initiator)) {
++iterator;
return false;
}
return true;
}
template <class CurrentClass>
static bool count_and_iterate(Actor& output, std::size_t index,
std::size_t& iterator) {
if (index != iterator) {
++iterator;
return false;
}
output = [](Vs... args) -> Root* {
return static_cast<Root*>(
new CurrentClass(std::forward<Vs>(args)...));
};
return true;
}
};
};
};
#define COMMA ,
#define MATCH_TO_FROM(what, to, from) \
Match##what::To##to::From##from::constructor