diff options
author | Jan Huwald <jh@sotun.de> | 2012-05-07 20:01:51 (GMT) |
---|---|---|
committer | Jan Huwald <jh@sotun.de> | 2012-05-07 20:01:51 (GMT) |
commit | 420d2ef464d4a741028e132e662d5626806a41f5 (patch) | |
tree | 1aca6eb512e4ed0fb5f3c10c528cb998b6ffd695 /core/template_helpers.hpp |
Diffstat (limited to 'core/template_helpers.hpp')
-rw-r--r-- | core/template_helpers.hpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/core/template_helpers.hpp b/core/template_helpers.hpp new file mode 100644 index 0000000..01a27b5 --- /dev/null +++ b/core/template_helpers.hpp @@ -0,0 +1,121 @@ +#ifndef LY1b9novVl8oDseRTw8dH5lzpNo +#define LY1b9novVl8oDseRTw8dH5lzpNo + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_empty.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_fundamental.hpp> +#include <boost/mpl/unpack_args.hpp> +#include <boost/mpl/list.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/mpl/next.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/pop_front.hpp> + + +#define STATIC_ASSERT_IS_POWER_OF_TWO(x) BOOST_STATIC_ASSERT( !(x & (x-1)) ); + +template<typename T, long long numerator, long long denominator = 1> +struct StaticVal { + inline static const T value() { return T(numerator) / T(denominator); } +}; + +// forcing a type conversion of non-ptr types +#define FORCE_CONV(Type, Val) (*(reinterpret_cast<Type *>(& Val))) + +// generate a constructor which fails when called +// TODO (beauty): catch error after optimization, before runtime +// (e.g. by linking to a forbidden symbol) +#define GEN_ANYCAST_CTOR_3(name) \ + template<class T1, class T2, class T3> name(T1 t1, T2 t2, T3 t3) + +// a void you may return +struct Void { + typedef Void type; // for metaprogramming brainfucks + typedef Void con_arg_t; +}; + +// just to beautify some code +struct BaseCase {}; + +// prevent instanciation of default or unimplemented cases +#define DO_NOT_INSTANCE(T) BOOST_STATIC_ASSERT((false && boost::is_same<T,T>::value)); + +// forward decl of a function which will never exist (allows showing +// errors at link time: later than DO_NOT_INSTANCE but before +// assert(false) +void oOoOo_LINK_TIME_ASSERTION_FAILED_oOoOo() __attribute__ ((noreturn)); +#define DO_NOT_CALL {oOoOo_LINK_TIME_ASSERTION_FAILED_oOoOo();} + +namespace UnpackTypeListImpl { + +using namespace boost::mpl; + +template<template<typename... T> class Tgt, + typename Iter, typename EndIter, + typename... NewList> +struct Action { + typedef typename Action<Tgt, + typename next<Iter>::type, EndIter, + NewList..., + typename deref<Iter>::type + >::type type; +}; + +template<template<typename... T> class Tgt, typename EndIter, typename... List> +struct Action<Tgt, EndIter, EndIter, List...> { + typedef Tgt<List...> type; +}; + +} // NS + +// unpack a boost::mpl sequence into a variadic type list +template<template<typename... T> class Tgt, + typename Seq, + typename... NewList> +struct UnpackTypeList { + typedef typename UnpackTypeListImpl + ::Action<Tgt, + typename boost::mpl::begin<Seq>::type, + typename boost::mpl::end<Seq>::type, + NewList...>::type type; +}; + +// create a unique class from a type, given a variadic garbage type +// list; if the type is an empty struct it is not stored but created +// upon every request +// TODO: access functions (right now the stored values are only +// accessed using outraging pointer casts) +template<typename T, bool isEmpty, bool isFund, typename... Garbage> struct MakeUniqueImpl; + +template<typename T, typename... Garbage> +struct MakeUnique { + typedef MakeUniqueImpl<T, boost::is_empty<T>::value, + boost::is_fundamental<T>::value, Garbage...> type; +}; + +template<typename T, typename... Garbage> +struct MakeUniqueImpl<T, true, false, Garbage...> { + MakeUniqueImpl(const T &v) {} + MakeUniqueImpl(T &&v) {} + MakeUniqueImpl() = default; +}; + +template<typename T, typename... Garbage> +struct MakeUniqueImpl<T, false, true, Garbage...> { + MakeUniqueImpl(const T &v) : v(v) {} + MakeUniqueImpl(T &&v) : v(v) {} + MakeUniqueImpl() = default; + T v; +}; + +template<typename T, typename... Garbage> +struct MakeUniqueImpl<T, false, false, Garbage...> : protected T { + MakeUniqueImpl(T&& a) : T(std::move(a)) {} + MakeUniqueImpl() = default; +}; + +#endif // LY1b9novVl8oDseRTw8dH5lzpNo |