Honeycomb  0.1
Component-Model Framework
Meta.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
5 
6 namespace honey
7 {
8 
10 
13 
16 namespace mt
17 {
18 
20 #define mt_unused(Param) (void)Param;
21 #define mt_unpackEval(...) mt::pass(((__VA_ARGS__), 0)...)
23 
25 template<class T> struct identity { typedef T type; };
27 template<class... Args> void pass(Args...) {}
29 template<class T, T val> using Value = std::integral_constant<T, val>;
31 template<class...> struct True : std::true_type {};
33 template<int64...> struct True_int : std::true_type {};
37 struct Void {};
39 template<int> struct tag { tag() = default; tag(int) {} };
40 
42 template<class T> using addRef = std::add_lvalue_reference<T>;
44 template<class T> using removeRef = std::remove_reference<T>;
46 template<class T> using addPtr = std::add_pointer<T>;
48 template<class T> using removePtr = std::remove_pointer<T>;
51 
59 template<class T> using isPtr = Value<bool, std::is_pointer<T>::value>;
60 
62 template<bool b, class T = void> using disable_if = std::enable_if<!b, T>;
63 
65 template<bool b, int64 t, int64 f> struct conditional_int : Value<int64, f> {};
66 template<int64 t, int64 f> struct conditional_int<true, t, f> : Value<int64, t> {};
67 
69 template<class Base, class Derived> struct is_base_of : std::is_base_of<typename removeRef<Base>::type, typename removeRef<Derived>::type> {};
70 
72 template<class T, template<class...> class Template>
73 struct isSpecializationOf : std::false_type {};
74 template<template<class...> class Template, class... Param>
75 struct isSpecializationOf<Template<Param...>, Template> : std::true_type {};
76 
78 template<class T> using isTuple = isSpecializationOf<typename std::decay<T>::type, tuple>;
79 
81 template<class Func, class... Args>
83 {
84  template<class F> static auto test(void*) -> decltype(declval<F>()(declval<Args>()...), std::true_type());
85  template<class F> static std::false_type test(...);
86 public:
87  static const bool value = isTrue<decltype(test<Func>(nullptr))>::value;
88 };
89 
91 namespace priv
92 {
93  template<int cur, int end, class... Ts> struct typeAt;
94  template<int cur, int end, class T, class... Ts> struct typeAt<cur, end, T, Ts...> : typeAt<cur+1, end, Ts...> {};
95  template<int cur, class T, class... Ts> struct typeAt<cur, cur, T, Ts...> { typedef T type; };
96  template<int cur, int end> struct typeAt<cur, end> {};
97 
98  template<int cur, class Match, class... Ts> struct typeIndex;
99  template<int cur, class Match, class T, class... Ts> struct typeIndex<cur, Match, T, Ts...> : typeIndex<cur+1, Match, Ts...> {};
100  template<int cur, class T, class... Ts> struct typeIndex<cur, T, T, Ts...> : Value<int, cur> {};
101  template<int cur, class Match> struct typeIndex<cur, Match> : Value<int, -1> {};
102 }
105 template<int I, class... Ts> using typeAt = typename priv::typeAt<0, I, Ts...>::type;
108 template<class Match, class... Ts> using typeIndex = priv::typeIndex<0, Match, Ts...>;
109 
111 template<szt... Ints> using idxseq = std::index_sequence<Ints...>;
113 template<szt N> using make_idxseq = std::make_index_sequence<N>;
114 
116 namespace priv
117 {
118  template<class Func, class Tuple, szt... Seq>
119  auto applyTuple(Func&& f, Tuple&& t, idxseq<Seq...>) { return f(get<Seq>(forward<Tuple>(t))...); }
120 }
123 template<class Func, class Tuple>
125 auto applyTuple(Func&& f, Tuple&& t) { return priv::applyTuple(forward<Func>(f), forward<Tuple>(t), make_idxseq<tuple_size<typename removeRef<Tuple>::type>::value>()); }
126 
128 template<class Array> using arraySize = Value<szt, sizeof(Array) / sizeof(typename Array::value_type)>;
129 
131 template<class T, class... Ts>
132 auto make_array(T&& t, Ts&&... ts) -> array<T, sizeof...(Ts)+1> { return {forward<T>(t), forward<Ts>(ts)...}; }
133 
134 inline void exec() {} //dummy to catch empty parameter pack
136 template<class Func, class... Funcs>
137 void exec(Func&& f, Funcs&&... fs) { f(); exec(forward<Funcs>(fs)...); }
138 
140 template<int64 begin, int64 end, int64 step = 1, class Func, class... Args, typename std::enable_if<begin == end, int>::type=0>
141 void for_(Func&& f, Args&&... args) {}
142 template<int64 begin, int64 end, int64 step = 1, class Func, class... Args, typename std::enable_if<begin != end, int>::type=0>
143 void for_(Func&& f, Args&&... args) { f(begin, forward<Args>(args)...); for_<begin+step, end, step>(forward<Func>(f), forward<Args>(args)...); }
144 
146 
156 #define mt_hasMember(MemberName) mt_hasMember2(MemberName, MemberName)
157 #define mt_hasMember2(MemberName, TestName) \
158  template<class Class, class MemberType> \
159  class mt_hasMember_##TestName \
160  { \
161  template<class T, T> struct matchType; \
162  template<class T> static auto memberMatch(void*) -> decltype(declval<matchType<MemberType, &T::MemberName>>(), std::true_type()); \
163  template<class T> static std::false_type memberMatch(...); \
164  public: \
165  static const bool value = mt::isTrue<decltype(memberMatch<Class>(nullptr))>::value; \
166  typedef typename std::conditional<value, MemberType, mt::Void>::type type; \
167  };
168 
169 
171 
181 #define mt_hasType(TypeName) mt_hasType2(TypeName, TypeName)
182 #define mt_hasType2(TypeName, TestName) \
183  template<class Class> \
184  class mt_hasType_##TestName \
185  { \
186  template<class T> static auto test(void*) -> decltype(declval<typename T::TypeName>(), std::true_type()); \
187  template<class T> static std::false_type test(...); \
188  \
189  template<bool Res, class Enable = void> \
190  struct testType { typedef mt::Void type; }; \
191  template<bool Res> \
192  struct testType<Res, typename std::enable_if<Res>::type> { typedef typename Class::TypeName type; }; \
193  public: \
194  static const bool value = mt::isTrue<decltype(test<Class>(nullptr))>::value; \
195  typedef typename testType<value>::type type; \
196  };
197 
198 
200 namespace priv
201 {
202  mt_hasType(iterator_category)
203  template<class T> struct isIterator : Value<bool, mt_hasType_iterator_category<T>::value || isPtr<T>::value> {};
204 }
207 template<class T> using isIterator = priv::isIterator<typename removeRef<T>::type>;
209 
211 
227 template<class T> struct funcTraits;
228 
229 
231 struct FuncptrBase {};
232 
233 template<class Sig> struct Funcptr;
234 
236 template<class R, class... Args>
237 struct Funcptr<R (Args...)>
238 {
239  typedef R (FuncptrBase::*Func)(Args...);
240 
241  Funcptr() : base(nullptr), func(nullptr) {}
242  Funcptr(nullptr_t) : Funcptr() {}
243  template<class F> Funcptr(F&& f) { operator=(forward<F>(f)); }
244  template<class F> Funcptr& operator=(F&& f) { base = &f; func = static_cast<Func>(&removeRef<F>::type::operator()); return *this; }
245  Funcptr& operator=(nullptr_t) { base = nullptr; func = nullptr; return *this; }
246  template<class... Args_>
247  R operator()(Args_&&... args) const { return (base->*func)(forward<Args_>(args)...); }
248  bool operator==(const Funcptr& rhs) const { return base == rhs.base && func == rhs.func; }
249  bool operator!=(const Funcptr& rhs) const { return !operator==(rhs); }
250  explicit operator bool() const { return base && func; }
251 
253  Func func;
254 };
255 
257 template<class... Args>
258 struct Funcptr<void (Args...)>
259 {
260  typedef void (FuncptrBase::*Func)(Args...);
261 
262  Funcptr() : base(nullptr), func(nullptr) {}
263  Funcptr(nullptr_t) : Funcptr() {}
264  template<class F> Funcptr(F&& f) { operator=(forward<F>(f)); }
265  template<class F> Funcptr& operator=(F&& f) { base = &f; func = static_cast<Func>(&removeRef<F>::type::operator()); return *this; }
266  Funcptr& operator=(nullptr_t) { base = nullptr; func = nullptr; return *this; }
267  template<class... Args_>
268  void operator()(Args_&&... args) const { (base->*func)(forward<Args_>(args)...); }
269  bool operator==(const Funcptr& rhs) const { return base == rhs.base && func == rhs.func; }
270  bool operator!=(const Funcptr& rhs) const { return !operator==(rhs); }
271  explicit operator bool() const { return base && func; }
272 
274  Func func;
275 };
276 
278 template<class F, class Sig = typename funcTraits<typename removeRef<F>::type>::Sig>
279 Funcptr<Sig> FuncptrCreate(F&& f) { return Funcptr<Sig>(forward<F>(f)); }
280 
281 
283 #define mt_global(Class, Func, Ctor) inline UNBRACKET(Class)& Func() { static UNBRACKET(Class) obj Ctor; return obj; }
284 
286 struct NoCopy
287 {
288  NoCopy(const NoCopy&) = delete;
289  NoCopy& operator=(const NoCopy&) = delete;
290 protected:
291  NoCopy() = default;
292 };
293 
295 
296 template<int64... vals> struct min;
297 template<int64 val, int64... vals> struct min<val, vals...> : Value<int64, (val < min<vals...>::value ? val : min<vals...>::value)> {};
298 template<int64 val> struct min<val> : Value<int64, val> {};
299 
301 
302 template<int64... vals> struct max;
303 template<int64 val, int64... vals> struct max<val, vals...> : Value<int64, (val > max<vals...>::value ? val : max<vals...>::value)> {};
304 template<int64 val> struct max<val> : Value<int64, val> {};
305 
307 template<int64 val> using abs = Value<int64, (val < 0) ? -val : val>;
309 template<int64 val> using sign = Value<int64, (val < 0) ? -1 : 1>;
310 
312 template<uint64 x> struct log2Floor : Value<int, log2Floor<x/2>::value+1> {};
313 template<> struct log2Floor<0> : Value<int, -1> {};
314 
316 template<int64 a, int64 b> struct gcd : gcd<b, a % b> {};
317 template<int64 a> struct gcd<a, 0> : Value<int64, abs<a>::value> {};
318 template<int64 b> struct gcd<0, b> : Value<int64, abs<b>::value> {};
319 
321 namespace priv
322 {
323  template<uint64 N> struct byteCount : Value<int, ((max<log2Floor<N>::value, 1>::value + 7) >> 3)> {};
324 
325  template<uint64 N> struct byteType : identity<uint64> {};
326  template<> struct byteType<4> : identity<uint32> {};
327  template<> struct byteType<3> : identity<uint32> {};
328  template<> struct byteType<2> : identity<uint16> {};
329  template<> struct byteType<1> : identity<uint8> {};
330 }
333 template<uint64 N> struct uintByValue : priv::byteType<priv::byteCount<N>::value> {};
336 template<int N> struct uintBySize : priv::byteType<N> {};
337 
338 //====================================================
339 // funcTraits
340 //====================================================
342 namespace priv
343 {
344  template<class T> struct functorTraits {};
345 }
348 template<class T> struct funcTraits : priv::functorTraits<decltype(&T::operator())> {};
349 
351 #define TRAITS(Ptr) \
352  template<class R, class... Args> \
353  struct funcTraits<R Ptr (Args...)> \
354  { \
355  typedef R Sig(Args...); \
356  typedef void Base; \
357  typedef R Return; \
358  static const szt arity = sizeof...(Args); \
359  template<szt I> using param = typeAt<I, Args...>; \
360  }; \
361 
362 #define M_TRAITS(Const) \
363  template<class R, class Base_, class... Args> \
364  struct funcTraits<R (Base_::*) (Args...) Const> \
365  { \
366  typedef R (Base_::*Sig) (Args...) Const; \
367  typedef Base_ Base; \
368  typedef R Return; \
369  static const szt arity = sizeof...(Args)+1; \
370  private: \
371  template<szt I, szt _=0> struct param_ { typedef typeAt<I-1, Args...> type; }; \
372  template<szt _> struct param_<0, _> { typedef Const Base* type; }; \
373  public: \
374  template<szt I> using param = typename param_<I>::type; \
375  }; \
376  \
377  namespace priv \
378  { \
379  template<class R, class Base_, class... Args> \
380  struct functorTraits<R (Base_::*) (Args...) Const> \
381  { \
382  typedef R Sig(Args...); \
383  typedef void Base; \
384  typedef R Return; \
385  static const szt arity = sizeof...(Args); \
386  template<szt I> using param = mt::typeAt<I, Args...>; \
387  }; \
388  } \
389 
390 TRAITS()
391 TRAITS(&)
392 TRAITS(*)
393 M_TRAITS()
394 M_TRAITS(const)
395 #undef TRAITS
396 #undef M_TRAITS
397 
398 //====================================================
400 
401 } }
priv::typeIndex< 0, Match, Ts... > typeIndex
Get index of first matching type in parameter pack, returns -1 if not found.
Definition: Meta.h:108
Value< szt, sizeof(Array)/sizeof(typename Array::value_type)> arraySize
Get size (number of elements) of a std::array.
Definition: Meta.h:128
Get maximum of all arguments.
Definition: Meta.h:302
bool operator==(const Funcptr &rhs) const
Definition: Meta.h:248
void for_(Func &&f, Args &&...args)
Unroll a loop calling f(counter, args...) at each iteration.
Definition: Meta.h:141
FuncptrBase * base
Definition: Meta.h:273
Version of std::is_base_of that removes reference qualifiers before testing.
Definition: Meta.h:69
auto make_array(T &&t, Ts &&...ts) -> array< T, sizeof...(Ts)+1 >
Create an array of deduced type initialized with values.
Definition: Meta.h:132
FuncptrBase * base
Definition: Meta.h:252
Value< bool, std::is_rvalue_reference< T >::value > isRref
Check if type is an rvalue reference.
Definition: Meta.h:55
Funcptr()
Definition: Meta.h:241
Funcptr & operator=(F &&f)
Definition: Meta.h:244
Value< bool, std::is_lvalue_reference< T >::value > isLref
Check if type is an lvalue reference.
Definition: Meta.h:53
Funcptr(nullptr_t)
Definition: Meta.h:242
Definition: Meta.h:233
Inherit to declare that class is not copyable.
Definition: Meta.h:286
Funcptr(F &&f)
Definition: Meta.h:264
Value< bool, std::is_same< T, std::true_type >::value > isTrue
Check if type is std::true_type.
Definition: Meta.h:35
std::enable_if<!b, T > disable_if
Opposite of std::enable_if.
Definition: Meta.h:62
std::add_pointer< T > addPtr
Add pointer to type.
Definition: Meta.h:46
Func func
Definition: Meta.h:253
Check if T is a specialization of Template.
Definition: Meta.h:73
Funcptr(nullptr_t)
Definition: Meta.h:263
std::integral_constant< T, val > Value
Holds a constant integral value.
Definition: Meta.h:29
std::index_sequence< Ints... > idxseq
Shorthand for std::index_sequence.
Definition: Meta.h:111
void pass(Args...)
Do nothing, can be used to evaluate an unpack expression.
Definition: Meta.h:27
std::remove_reference< T > removeRef
Remove reference from type.
Definition: Meta.h:44
Value< int64,(val< 0)?-val:val > abs
Get the absolute value of a number.
Definition: Meta.h:307
Variant of std::conditional for integers, stores result in value
Definition: Meta.h:65
static const bool value
Definition: Meta.h:87
std::remove_pointer< T > removePtr
Remove pointer from type.
Definition: Meta.h:48
tag(int)
Definition: Meta.h:39
bool operator!=(const Funcptr &rhs) const
Definition: Meta.h:249
Value< int64,(val< 0)?-1:1 > sign
Get the sign of a number.
Definition: Meta.h:309
void exec()
Definition: Meta.h:134
Special void type, use where void is intended but implicit members are required (default ctor...
Definition: Meta.h:37
void operator()(Args_ &&...args) const
Definition: Meta.h:268
Funcptr & operator=(F &&f)
Definition: Meta.h:265
Get function type traits.
Definition: Meta.h:227
R operator()(Args_ &&...args) const
Definition: Meta.h:247
Value< bool, std::is_reference< T >::value > isRef
Check if type is a reference.
Definition: Meta.h:57
bool operator==(const Funcptr &rhs) const
Definition: Meta.h:269
Always returns true. Can be used to force a clause to be type dependent.
Definition: Meta.h:31
Value< bool, std::is_pointer< T >::value > isPtr
Check if type is a pointer.
Definition: Meta.h:59
Func func
Definition: Meta.h:274
Funcptr()
Definition: Meta.h:262
Calc greatest common divisor of a and b.
Definition: Meta.h:316
Use to differentiate an overloaded function by type. Accepts dummy parameter default value: func(tag<...
Definition: Meta.h:39
size_t szt
Size type, shorthand for size_t.
Definition: Core.h:90
typename priv::typeAt< 0, I, Ts... >::type typeAt
Get type at index of parameter pack.
Definition: Meta.h:106
T type
Definition: Meta.h:25
Funcptr< Sig > FuncptrCreate(F &&f)
Convenient method to create a Funcptr from a functor that inherits from FuncptrBase.
Definition: Meta.h:279
Variant of True for integers.
Definition: Meta.h:33
Funcptr & operator=(nullptr_t)
Definition: Meta.h:245
NoCopy & operator=(const NoCopy &)=delete
std::make_index_sequence< N > make_idxseq
Shorthand for std::make_index_sequence.
Definition: Meta.h:113
long long int64
Definition: Core.h:21
Funcptr & operator=(nullptr_t)
Definition: Meta.h:266
Calc log base 2 of unsigned integer, rounded down to nearest integer. Returns -1 if x is zero...
Definition: Meta.h:312
bool operator==(const String &lhs, const String &rhs)
Definition: String.h:139
bool operator!=(const Funcptr &rhs) const
Definition: Meta.h:270
Returns type T unchanged.
Definition: Meta.h:25
Check if functor is callable with arguments.
Definition: Meta.h:82
addRef< typename std::add_const< T >::type > addConstRef
Add top-level const qualifier and reference to type. Use std::decay to remove top-level const/ref...
Definition: Meta.h:50
auto applyTuple(Func &&f, Tuple &&t)
Call a function with arguments from an unpacked tuple. ie. f(get(t)...)
Definition: Meta.h:125
std::add_lvalue_reference< T > addRef
Add reference to type.
Definition: Meta.h:42
Inherit to enable non-virtual functor calling.
Definition: Meta.h:231
Get minimum of all arguments.
Definition: Meta.h:296
Global Honeycomb namespace.
Funcptr(F &&f)
Definition: Meta.h:243
priv::isIterator< typename removeRef< T >::type > isIterator
Check if type is an iterator or a reference to one. An iterator is a type that has member iterator_ca...
Definition: Meta.h:208
#define mt_hasType(TypeName)
Create a method to check if a class has a nested type/class.
Definition: Meta.h:181