-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcore_componente.h
139 lines (124 loc) · 2.84 KB
/
core_componente.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
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once
#include <stdlib.h>
namespace util
{
template <typename T, typename U>
struct is_same {
enum { value = 0 };
};
template <typename T>
struct is_same<T, T> {
enum { value = 1 };
};
/**
* Funcion que toma un array de bools, y su tamaño y devuelve el resultado de reducirlo con OR.
*/
template <typename B, typename... Bs>
struct or_templ;
template <typename B>
struct or_templ<B>
{
static const bool value = B::value;
};
template <typename B, typename... Bs>
struct or_templ
{
static const bool value = B::value || or_templ<Bs...>::value;
};
}
namespace core
{
template <typename... Comp>
class cont_comp;
/**
* Template para terminar la recursion.
*/
template <>
class cont_comp<>
{};
/**
* Contenedor para componentes.
* Cada componente debe tener un constructor default e implementar la funcion
* actualizar().
*/
template <typename PComp, typename... Comp>
class cont_comp<PComp, Comp...>
{
PComp comp_;
cont_comp<Comp...> resto_comp_;
/**
* Template recursiva para buscar un tipo.
*/
template <typename CompBus, bool IsSame>
struct _rec_buscar;
/**
* Caso usado cuando el tipo buscado esta en este nivel del contenedor.
*/
template <typename CompBus>
struct _rec_buscar<CompBus, true>
{
inline CompBus& operator()(cont_comp<PComp, Comp...>& cont)
{
return cont.comp_;
}
};
/**
* Caso para cuando el tipo está en un subnivel del contenedor.
*/
template <typename CompBus>
struct _rec_buscar<CompBus, false>
{
inline CompBus& operator()(cont_comp<PComp, Comp...>& cont)
{
return cont.resto_comp_.buscar<CompBus>();
}
};
/**
* Template recursiva para actualizar los sistemas.
*/
template <typename... ActComp>
struct _rec_actualizar;
/**
* Caso recursivo.
*/
template <typename PActComp, typename SActComp, typename... ActComp>
struct _rec_actualizar<PActComp, SActComp, ActComp...>
{
inline void operator()(cont_comp<PComp, SActComp, ActComp...>& cont)
{
cont.comp_.actualizar();
cont.resto_comp_.actualizar();
}
};
/**
* Solo se usa cuando sizeof...(ActComp) == 0.
*/
template <typename PActComp, typename... ActComp>
struct _rec_actualizar<PActComp, ActComp...>
{
inline void operator()(cont_comp<PActComp, ActComp...>& cont)
{
static_assert(sizeof...(ActComp) == 0, "debería usarse la anterior especializacion");
cont.comp_.actualizar();
}
};
public:
/**
* Funcion para buscar un componente.
*/
template <typename CompBus>
inline CompBus& buscar()
{
static_assert(util::or_templ<util::is_same<CompBus, PComp>, util::is_same<CompBus, Comp>...>::value, "El tipo buscado no está en el contenedor");
return _rec_buscar<CompBus, util::is_same<CompBus, PComp>::value>()(*this);
}
/**
* Funcion que actualiza los componentes de acuerdo con el
* estado del mundo exterior.
*/
void actualizar()
{
_rec_actualizar<PComp, Comp...>()(*this);
}
};
}