thesis version
This commit is contained in:
		
							
								
								
									
										7
									
								
								inc/tmp/algorithm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								inc/tmp/algorithm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#ifndef TMP_ALGORITHM_H
 | 
			
		||||
#define TMP_ALGORITHM_H
 | 
			
		||||
 | 
			
		||||
#include "packalgo.h"
 | 
			
		||||
#include "treealgo.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										17
									
								
								inc/tmp/bind.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								inc/tmp/bind.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#include "packalgo.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
template<template<typename...> class TT, typename C>
 | 
			
		||||
struct Bind2nd {
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	using F1 = TT<T, C>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename ValueType, template<typename, ValueType, typename...> class TT, ValueType V>
 | 
			
		||||
struct Bind2ndV {
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	using F1 = TT<T, V>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										78
									
								
								inc/tmp/debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								inc/tmp/debug.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#ifndef TMP_DEBUG_H
 | 
			
		||||
#define TMP_DEBUG_H
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file tmp/debug.h
 | 
			
		||||
 * @brief compile-time typename to string resolution
 | 
			
		||||
 *
 | 
			
		||||
 * see: https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
 | 
			
		||||
 * see: https://stackoverflow.com/a/20170989
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted, minimal C++ version supported is C++14
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include "stringview.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
constexpr unsigned strlen(char const*str) {
 | 
			
		||||
	unsigned l = 0;
 | 
			
		||||
	while(*str++) ++l;
 | 
			
		||||
	return l;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief compile-time typename to string resolution
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] T type to resolve
 | 
			
		||||
 *
 | 
			
		||||
 * @return constexpr string_view containing the typename
 | 
			
		||||
 *
 | 
			
		||||
 * TODO this function has not been tested for Windows
 | 
			
		||||
 */
 | 
			
		||||
template<typename T>
 | 
			
		||||
constexpr string_view typeName() {
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
	string_view p = __PRETTY_FUNCTION__;
 | 
			
		||||
	constexpr auto leftDummy = detail::strlen("tmp::string_view tmp::typeName() [T = ");
 | 
			
		||||
	constexpr auto rightDummy = detail::strlen("]");
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
	string_view p = __PRETTY_FUNCTION__;
 | 
			
		||||
	constexpr auto leftDummy = detail::strlen("constexpr tmp::string_view tmp::typeName() [with T = ");
 | 
			
		||||
	constexpr auto rightDummy = detail::strlen("]");
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
	string_view p = __FUNCSIG__;
 | 
			
		||||
	constexpr auto leftDummy = detail::strlen("");
 | 
			
		||||
	constexpr auto rightDummy = detail::strlen("");
 | 
			
		||||
#else
 | 
			
		||||
	return {"[err: tmp::typeNameF is not implemented for your compiler]"};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__) || defined(__GNUC__) || defined(__MSC_VER)
 | 
			
		||||
	return string_view(p.data() + leftDummy, p.size() - leftDummy - rightDummy);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename... As, typename... Ts>
 | 
			
		||||
std::string strTypes(Ts...) {
 | 
			
		||||
	using Fold = int[];
 | 
			
		||||
	std::string result;
 | 
			
		||||
	static_cast<void>(Fold{(result += std::string{typeName<As>()} + ", ", 0)...});
 | 
			
		||||
	static_cast<void>(Fold{(result += std::string{typeName<Ts>()} + ", ", 0)...});
 | 
			
		||||
	if(result.empty())  return "";
 | 
			
		||||
	else                return result.substr(0, result.size()-2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename... As, typename... Ts>
 | 
			
		||||
void printTypes(Ts...) {
 | 
			
		||||
	std::puts(strTypes<As..., Ts...>().c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										167
									
								
								inc/tmp/pack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								inc/tmp/pack.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,167 @@
 | 
			
		||||
#ifndef TMP_PACK_H
 | 
			
		||||
#define TMP_PACK_H
 | 
			
		||||
 | 
			
		||||
#include "utility.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Pack
 | 
			
		||||
 */
 | 
			
		||||
template<typename... Ts> struct Pack {
 | 
			
		||||
	static constexpr Size size = sizeof...(Ts);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackHead
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct PackHeadImpl;
 | 
			
		||||
template<typename T, typename... Ts>
 | 
			
		||||
struct PackHeadImpl<Pack<T, Ts...>> {
 | 
			
		||||
	using type = T;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using PackHead = typename PackHeadImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackTrail
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct PackTrailImpl;
 | 
			
		||||
template<typename T, typename... Ts>
 | 
			
		||||
struct PackTrailImpl<Pack<T, Ts...>> {
 | 
			
		||||
	using type = Pack<Ts...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using PackTrail = typename PackTrailImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackGet
 | 
			
		||||
 */
 | 
			
		||||
template<typename, Size> struct PackGetImpl;
 | 
			
		||||
 | 
			
		||||
template<typename T, typename... Ts, Size I>
 | 
			
		||||
struct PackGetImpl<Pack<T, Ts...>, I> {
 | 
			
		||||
	using type = typename PackGetImpl<Pack<Ts...>, I-1>::type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, typename... Ts>
 | 
			
		||||
struct PackGetImpl<Pack<T, Ts...>, 0> {
 | 
			
		||||
	using type = T;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, Size I>
 | 
			
		||||
using PackGet = typename PackGetImpl<T, I>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackPushFront
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename> struct PackPushFrontImpl;
 | 
			
		||||
 | 
			
		||||
template<typename... Ts, typename T>
 | 
			
		||||
struct PackPushFrontImpl<Pack<Ts...>, T> {
 | 
			
		||||
	using type = Pack<T, Ts...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, typename T>
 | 
			
		||||
using PackPushFront = typename PackPushFrontImpl<P, T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackPushBack
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename> struct PackPushBackImpl;
 | 
			
		||||
 | 
			
		||||
template<typename... Ts, typename T>
 | 
			
		||||
struct PackPushBackImpl<Pack<Ts...>, T> {
 | 
			
		||||
	using type = Pack<Ts..., T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, typename T>
 | 
			
		||||
using PackPushBack = typename PackPushBackImpl<P, T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackCat
 | 
			
		||||
 */
 | 
			
		||||
template<typename...> struct PackCatImpl;
 | 
			
		||||
 | 
			
		||||
template<typename... Ts, typename... Us, typename... Packs>
 | 
			
		||||
struct PackCatImpl<Pack<Ts...>, Pack<Us...>, Packs...> {
 | 
			
		||||
	using type = typename PackCatImpl<Pack<Ts..., Us...>, Packs...>::type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Ts>
 | 
			
		||||
struct PackCatImpl<Pack<Ts...>> {
 | 
			
		||||
	using type = Pack<Ts...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct PackCatImpl<> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Packs>
 | 
			
		||||
using PackCat = typename PackCatImpl<Packs...>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackReverse
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct PackReverseImpl;
 | 
			
		||||
 | 
			
		||||
template<typename T, typename... Ts>
 | 
			
		||||
struct PackReverseImpl<Pack<T, Ts...>> {
 | 
			
		||||
	using type = PackPushBack<typename PackReverseImpl<Pack<Ts...>>::type, T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct PackReverseImpl<Pack<>> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P>
 | 
			
		||||
using PackReverse = typename PackReverseImpl<P>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackReplace
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename, typename> struct PackReplaceImpl;
 | 
			
		||||
 | 
			
		||||
template<typename Before, typename After, typename Current, typename... Ts>
 | 
			
		||||
struct PackReplaceImpl<Pack<Current, Ts...>, Before, After> {
 | 
			
		||||
	using type = PackCat<Pack<Current>, typename PackReplaceImpl<Pack<Ts...>, Before, After>::type>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename Before, typename After, typename... Ts>
 | 
			
		||||
struct PackReplaceImpl<Pack<Before, Ts...>, Before, After> {
 | 
			
		||||
	using type = PackCat<Pack<After>, typename PackReplaceImpl<Pack<Ts...>, Before, After>::type>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename Before, typename After>
 | 
			
		||||
struct PackReplaceImpl<Pack<>, Before, After> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, typename Before, typename After>
 | 
			
		||||
using PackReplace = typename PackReplaceImpl<P, Before, After>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Repack
 | 
			
		||||
 */
 | 
			
		||||
template<template<typename...> class, typename> struct RepackImpl;
 | 
			
		||||
template<template<typename...> class Out, template<typename...> class In, typename... Ts>
 | 
			
		||||
struct RepackImpl<Out, In<Ts...>> {
 | 
			
		||||
	using type = Out<Ts...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename...> class Out, typename In>
 | 
			
		||||
using Repack = typename RepackImpl<Out, In>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * AsPack
 | 
			
		||||
 */
 | 
			
		||||
template<typename T>
 | 
			
		||||
using AsPack = Repack<Pack, T>;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										103
									
								
								inc/tmp/packalgo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								inc/tmp/packalgo.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
#ifndef TMP_PACKALGO_H
 | 
			
		||||
#define TMP_PACKALGO_H
 | 
			
		||||
 | 
			
		||||
#include "pack.h"
 | 
			
		||||
#include "traits.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Transform
 | 
			
		||||
 */
 | 
			
		||||
template<typename, template<typename...> class> struct TransformImpl;
 | 
			
		||||
template<typename T, typename... Ts, template<typename...> class F>
 | 
			
		||||
struct TransformImpl<Pack<T, Ts...>, F> {
 | 
			
		||||
	using type = PackPushFront<typename TransformImpl<Pack<Ts...>, F>::type, F<T>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename...> class F>
 | 
			
		||||
struct TransformImpl<Pack<>, F> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, template<typename...> class F>
 | 
			
		||||
using Transform = typename TransformImpl<P, F>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Accumulate
 | 
			
		||||
 */
 | 
			
		||||
template<typename, template<typename, typename> class, typename> struct AccumulateImpl;
 | 
			
		||||
template<typename T, typename... Ts, template<typename, typename> class F, typename A>
 | 
			
		||||
struct AccumulateImpl<Pack<T, Ts...>, F, A> {
 | 
			
		||||
	using type = typename AccumulateImpl<Pack<Ts...>, F, F<A, T>>::type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename, typename> class F, typename A>
 | 
			
		||||
struct AccumulateImpl<Pack<>, F, A> {
 | 
			
		||||
	using type = A;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, template<typename, typename> class F, typename A>
 | 
			
		||||
using Accumulate = typename AccumulateImpl<P, F, A>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter
 | 
			
		||||
 */
 | 
			
		||||
template<typename, template<typename> class> struct FilterImpl;
 | 
			
		||||
template<typename T, typename... Ts, template<typename> class F>
 | 
			
		||||
struct FilterImpl<Pack<T, Ts...>, F> {
 | 
			
		||||
	using next = typename FilterImpl<Pack<Ts...>, F>::type;
 | 
			
		||||
	using type = std::conditional_t<F<T>::value, PackPushFront<next, T>, next>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename> class F>
 | 
			
		||||
struct FilterImpl<Pack<>, F> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, template<typename> class F>
 | 
			
		||||
using Filter = typename FilterImpl<P, F>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Cut
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename, template<typename> class> struct CutImpl;
 | 
			
		||||
template<typename R, typename... Rs, typename... Ls, template<typename> class F>
 | 
			
		||||
struct CutImpl<Pack<Ls...>, Pack<R, Rs...>, F> {
 | 
			
		||||
	using next = typename CutImpl<Pack<Ls..., R>, Pack<Rs...>, F>::type;
 | 
			
		||||
	using type = std::conditional_t<F<R>::value, next, Pack<Pack<Ls...>, Pack<R, Rs...>>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Ls, template<typename> class F>
 | 
			
		||||
struct CutImpl<Pack<Ls...>, Pack<>, F> {
 | 
			
		||||
	using type = Pack<Pack<Ls...>, Pack<>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename> class F>
 | 
			
		||||
struct CutImpl<Pack<>, Pack<>, F> {
 | 
			
		||||
	using type = Pack<Pack<>, Pack<>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P, template<typename> class F>
 | 
			
		||||
using Cut = typename CutImpl<Pack<>, P, F>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reverse
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct ReverseImpl;
 | 
			
		||||
template<typename T, typename... Ts>
 | 
			
		||||
struct ReverseImpl<Pack<T, Ts...>> {
 | 
			
		||||
	using type = PackPushBack<typename ReverseImpl<Pack<Ts...>>::type, T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct ReverseImpl<Pack<>> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using Reverse = typename ReverseImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										52
									
								
								inc/tmp/stringview.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								inc/tmp/stringview.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
#ifndef TMP_STRINGVIEW_H
 | 
			
		||||
#define TMP_STRINGVIEW_H
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file tmp/stringview.h"
 | 
			
		||||
 * @brief partial implementation of C++17 std::string_view
 | 
			
		||||
 *
 | 
			
		||||
 * see: https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
 | 
			
		||||
 * see: https://stackoverflow.com/a/20170989
 | 
			
		||||
 * string_view is from "static_string" class
 | 
			
		||||
 * to be replaced by std::string_view as soon as possible
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted, minimal C++ version supported now C++11
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
class string_view {
 | 
			
		||||
	char const* const _p;
 | 
			
		||||
	std::size_t const _sz;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	using const_iterator = char const*;
 | 
			
		||||
 | 
			
		||||
	template<std::size_t N>
 | 
			
		||||
	constexpr string_view(char const(&a)[N]) noexcept: _p(a), _sz(N-1) {}
 | 
			
		||||
	constexpr string_view(char const*p, std::size_t N) noexcept: _p(p), _sz(N) {}
 | 
			
		||||
 | 
			
		||||
	constexpr char const*data() const noexcept {return _p;}
 | 
			
		||||
	constexpr std::size_t size() const noexcept {return _sz;}
 | 
			
		||||
 | 
			
		||||
	constexpr const_iterator begin() const noexcept {return _p;}
 | 
			
		||||
	constexpr const_iterator end()   const noexcept {return _p + _sz;}
 | 
			
		||||
 | 
			
		||||
	constexpr char operator[](std::size_t n) const {
 | 
			
		||||
		return n < _sz? _p[n] : throw std::out_of_range("string_view");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	explicit operator std::string() const { return {_p, _sz}; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename Ostream>
 | 
			
		||||
inline Ostream&operator<<(Ostream &os, string_view const&s) {
 | 
			
		||||
	os.write(s.data(), s.size());
 | 
			
		||||
	return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										78
									
								
								inc/tmp/traits.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								inc/tmp/traits.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#ifndef TMP_TRAITS_H
 | 
			
		||||
#define TMP_TRAITS_H
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#include "pack.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * void_t
 | 
			
		||||
 *
 | 
			
		||||
 * as of C++17, use std::void_t instead
 | 
			
		||||
 */
 | 
			
		||||
template<typename...> using void_t = void;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Void
 | 
			
		||||
 *
 | 
			
		||||
 * use to replace `void` when an instance is required
 | 
			
		||||
 */
 | 
			
		||||
struct Void {};
 | 
			
		||||
 | 
			
		||||
// TODO: remove it?
 | 
			
		||||
template<typename Ostream>
 | 
			
		||||
Ostream &operator<<(Ostream &os, Void const&) {
 | 
			
		||||
	return os << "Void{}";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ReturnType
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct ReturnTypeImpl;
 | 
			
		||||
template<typename R, typename... Ts>
 | 
			
		||||
struct ReturnTypeImpl<R(Ts...)> {
 | 
			
		||||
	using type = R;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using ReturnType = typename ReturnTypeImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parameters
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct ParametersImpl;
 | 
			
		||||
template<typename R, typename... Ps>
 | 
			
		||||
struct ParametersImpl<R(Ps...)> {
 | 
			
		||||
	using type = Pack<Ps...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using Parameters = typename ParametersImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * invoke_result
 | 
			
		||||
 * as of C++17, use std::invoke_result instead
 | 
			
		||||
 */
 | 
			
		||||
template<typename F, typename... Args>
 | 
			
		||||
using invoke_result = std::result_of<F(Args...)>;
 | 
			
		||||
 | 
			
		||||
template<typename F, typename... Args>
 | 
			
		||||
using invoke_result_t = typename invoke_result<F, Args...>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * FunctionCat
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename> struct FunctionCatImpl;
 | 
			
		||||
 | 
			
		||||
template<typename Ret, typename... Ts, typename... Us>
 | 
			
		||||
struct FunctionCatImpl<Ret(Ts...), Ret(Us...)> {
 | 
			
		||||
	using type = Ret(Ts..., Us...);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename F1, typename F2>
 | 
			
		||||
using FunctionCat = typename FunctionCatImpl<F1, F2>::type;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										159
									
								
								inc/tmp/tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								inc/tmp/tree.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
#ifndef TMP_TREE_H
 | 
			
		||||
#define TMP_TREE_H
 | 
			
		||||
 | 
			
		||||
#include "bind.h"
 | 
			
		||||
#include "pack.h"
 | 
			
		||||
#include "packalgo.h"
 | 
			
		||||
#include "utility.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tree
 | 
			
		||||
 */
 | 
			
		||||
template<typename...> struct Tree;
 | 
			
		||||
 | 
			
		||||
template<typename N, typename... Cs>
 | 
			
		||||
struct Tree<N, Cs...> {
 | 
			
		||||
	using node      = N;
 | 
			
		||||
	using children  = Pack<Cs...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct Tree<> {};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeNode
 | 
			
		||||
 *
 | 
			
		||||
 * for use in flat tree representations
 | 
			
		||||
 */
 | 
			
		||||
enum class TreeNodeType { Branch, Leaf };
 | 
			
		||||
template<Depth D, typename T, TreeNodeType N>
 | 
			
		||||
struct TreeNode {
 | 
			
		||||
	static constexpr Depth depth            = D;
 | 
			
		||||
	using type                              = T;
 | 
			
		||||
	static constexpr TreeNodeType nodeType  = N;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, TreeNodeType NT = TreeNodeType::Branch>
 | 
			
		||||
using TreeRoot = TreeNode<0, T, NT>;
 | 
			
		||||
 | 
			
		||||
template<Depth D, typename T>
 | 
			
		||||
using TreeBranch = TreeNode<D, T, TreeNodeType::Branch>;
 | 
			
		||||
 | 
			
		||||
template<Depth D, typename T>
 | 
			
		||||
using TreeLeaf = TreeNode<D, T, TreeNodeType::Leaf>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeIsLeaf
 | 
			
		||||
 */
 | 
			
		||||
template<typename> struct TreeIsLeafImpl: std::true_type {};
 | 
			
		||||
template<typename... Ts>
 | 
			
		||||
struct TreeIsLeafImpl<Tree<Ts...>>: std::false_type {};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
constexpr bool TreeIsLeaf = TreeIsLeafImpl<T>::value;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PackFromTreeNLR
 | 
			
		||||
 *
 | 
			
		||||
 * creates a pack from a tree using NLR
 | 
			
		||||
 * tree traversal algorithm
 | 
			
		||||
 */
 | 
			
		||||
template<typename, Depth=0> struct PackFromTreeNLRImpl;
 | 
			
		||||
 | 
			
		||||
template<typename N, typename... LRs, Depth D>
 | 
			
		||||
struct PackFromTreeNLRImpl<Tree<N, LRs...>, D> {
 | 
			
		||||
	using type = PackPushFront<
 | 
			
		||||
		PackCat<typename PackFromTreeNLRImpl<LRs, D+1>::type...>,
 | 
			
		||||
		TreeBranch<D, N>
 | 
			
		||||
			>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename N, Depth D>
 | 
			
		||||
struct PackFromTreeNLRImpl<Tree<N>, D> {
 | 
			
		||||
	using type = Pack<TreeLeaf<D, N>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<Depth D>
 | 
			
		||||
struct PackFromTreeNLRImpl<Tree<>, D> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, Depth D = 0>
 | 
			
		||||
using PackFromTreeNLR = typename PackFromTreeNLRImpl<T, D>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeFromPackNLR
 | 
			
		||||
 *
 | 
			
		||||
 * creates a tree from a pack
 | 
			
		||||
 * reverses PackFromTreeNLR
 | 
			
		||||
 */
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template<Depth D, typename T>
 | 
			
		||||
using PartialTree = Pack<std::integral_constant<decltype(D), D>, T>;
 | 
			
		||||
 | 
			
		||||
template<Depth LIM>
 | 
			
		||||
struct GreaterThan {
 | 
			
		||||
	template<typename T, typename=void> struct CmpImpl;
 | 
			
		||||
	template<Depth D, typename T>
 | 
			
		||||
	struct CmpImpl<PartialTree<D, T>>: std::integral_constant<bool, (D > LIM)> {};
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	struct CmpImpl<T>: std::true_type {};
 | 
			
		||||
 | 
			
		||||
	template<typename T>
 | 
			
		||||
	using Cmp = CmpImpl<T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* property:
 | 
			
		||||
 * one block either groups future blocks or
 | 
			
		||||
 * has a bigger or equal depth than following
 | 
			
		||||
 *
 | 
			
		||||
 * property:
 | 
			
		||||
 * the list of depths when building is always
 | 
			
		||||
 * decreasing (quite easy to demonstrate)
 | 
			
		||||
 */
 | 
			
		||||
template<typename, typename=void> struct TreeFromPackNLRImpl;
 | 
			
		||||
 | 
			
		||||
template<Depth D, typename T, typename... Ns>
 | 
			
		||||
struct TreeFromPackNLRImpl<Pack<TreeBranch<D, T>, Ns...>, std::enable_if_t<D != 0>> {
 | 
			
		||||
	using next      = typename TreeFromPackNLRImpl<Pack<Ns...>>::subtree;
 | 
			
		||||
	using cutd      = Cut<next, detail::GreaterThan<D>::template Cmp>;
 | 
			
		||||
	using children  = Transform<PackGet<cutd, 0>, Bind2ndV<Size, PackGet, 1>::template F1>;
 | 
			
		||||
	using siblings  = PackGet<cutd, 1>;
 | 
			
		||||
	using part      = detail::PartialTree<D, Repack<Tree, PackPushFront<children, T>>>;
 | 
			
		||||
	using subtree   = PackPushFront<siblings, part>;
 | 
			
		||||
 | 
			
		||||
	using type      = Repack<Tree, subtree>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, TreeNodeType NT, typename... Ns>
 | 
			
		||||
struct TreeFromPackNLRImpl<Pack<TreeRoot<T, NT>, Ns...>> {
 | 
			
		||||
	using next      = typename TreeFromPackNLRImpl<Pack<Ns...>>::subtree;
 | 
			
		||||
	using children  = Transform<next, Bind2ndV<Size, PackGet, 1>::template F1>;
 | 
			
		||||
	using subtree   = PackPushFront<children, T>;
 | 
			
		||||
	using type      = Repack<Tree, subtree>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<Depth D, typename T, typename... Ns>
 | 
			
		||||
struct TreeFromPackNLRImpl<Pack<TreeLeaf<D, T>, Ns...>, std::enable_if_t<D != 0>> {
 | 
			
		||||
	using part    = detail::PartialTree<D, Tree<T>>;
 | 
			
		||||
	using subtree = PackPushFront<typename TreeFromPackNLRImpl<Pack<Ns...>>::subtree, part>;
 | 
			
		||||
	using type    = Repack<Tree, subtree>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct TreeFromPackNLRImpl<Pack<>> {
 | 
			
		||||
	using subtree = Pack<>;
 | 
			
		||||
	using type    = Repack<Tree, subtree>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename P>
 | 
			
		||||
using TreeFromPackNLR = typename TreeFromPackNLRImpl<P>::type;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										105
									
								
								inc/tmp/treealgo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								inc/tmp/treealgo.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
#ifndef TMP_TREEALGO_H
 | 
			
		||||
#define TMP_TREEALGO_H
 | 
			
		||||
 | 
			
		||||
#include "packalgo.h"
 | 
			
		||||
#include "tree.h"
 | 
			
		||||
#include "utility.h"
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeTransform
 | 
			
		||||
 */
 | 
			
		||||
template<typename, template<typename> class> struct TreeTransformImpl;
 | 
			
		||||
template<typename T, typename... Ts, template<typename> class F>
 | 
			
		||||
struct TreeTransformImpl<Tree<T, Ts...>, F> {
 | 
			
		||||
	using type = Tree<F<T>, typename TreeTransformImpl<Ts, F>::type...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename> class F>
 | 
			
		||||
struct TreeTransformImpl<Tree<>, F> {
 | 
			
		||||
	using type = Tree<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, template<typename> class F>
 | 
			
		||||
using TreeTransform = typename TreeTransformImpl<T, F>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeAccumulate
 | 
			
		||||
 */
 | 
			
		||||
template<typename, template<typename, typename...> class, typename> struct TreeAccumulateImpl;
 | 
			
		||||
template<typename T, typename... Ts, template<typename, typename...> class F, typename A>
 | 
			
		||||
struct TreeAccumulateImpl<Tree<T, Ts...>, F, A> {
 | 
			
		||||
	using type = F<T, typename TreeAccumulateImpl<Ts, F, A>::type...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, template<typename, typename...> class F, typename A>
 | 
			
		||||
struct TreeAccumulateImpl<Tree<T>, F, A> {
 | 
			
		||||
	using type = F<T, A>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<template<typename, typename...> class F, typename A>
 | 
			
		||||
struct TreeAccumulateImpl<Tree<>, F, A> {
 | 
			
		||||
	using type = A;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T, template<typename, typename...> class F, typename A>
 | 
			
		||||
using TreeAccumulate = typename TreeAccumulateImpl<T, F, A>::type;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeNLRAccumulate
 | 
			
		||||
 */
 | 
			
		||||
template<typename T, template<typename, typename> class F, typename A>
 | 
			
		||||
using TreeNLRAccumulate = Accumulate<Transform<PackFromTreeNLR<T>, GetType>, F, A>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeHeight
 | 
			
		||||
 */
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct TreeHeightImpl {
 | 
			
		||||
	template<typename, typename... Ts>
 | 
			
		||||
	using CalcHeight = std::integral_constant<Depth, 1 + detail::Max<Ts::type::value...>>;
 | 
			
		||||
	using CalcHeightDefault = std::integral_constant<Depth, -1>;
 | 
			
		||||
 | 
			
		||||
	static constexpr Depth value = TreeAccumulate<T, CalcHeight, CalcHeightDefault>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
constexpr Depth TreeHeight = TreeHeightImpl<T>::value;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TreeAllRTLPaths
 | 
			
		||||
 */
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct PackPushFronter {
 | 
			
		||||
	template<typename P>
 | 
			
		||||
	using Do = PackPushFront<P, T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename> struct TreeAllRTLPathsImpl;
 | 
			
		||||
 | 
			
		||||
template<typename N, typename... Cs>
 | 
			
		||||
struct TreeAllRTLPathsImpl<Tree<N, Cs...>> {
 | 
			
		||||
	using type = PackCat<Transform<typename TreeAllRTLPathsImpl<Cs>::type, Bind2nd<PackPushFront, N>::template F1>...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename N>
 | 
			
		||||
struct TreeAllRTLPathsImpl<Tree<N>> {
 | 
			
		||||
	using type  = Pack<Pack<N>>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
struct TreeAllRTLPathsImpl<Tree<>> {
 | 
			
		||||
	using type = Pack<>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using TreeAllRTLPaths = typename TreeAllRTLPathsImpl<T>::type;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										30
									
								
								inc/tmp/utility.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								inc/tmp/utility.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
#ifndef TMP_UTILITY_H
 | 
			
		||||
#define TMP_UTILITY_H
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
namespace tmp {
 | 
			
		||||
 | 
			
		||||
using Size = decltype(sizeof 0);
 | 
			
		||||
 | 
			
		||||
using Depth = signed long long int;
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
using GetType = typename T::type;
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template<Depth V, Depth... Vs>
 | 
			
		||||
struct MaxImpl: std::integral_constant<Depth, (V>MaxImpl<Vs...>::value? V:MaxImpl<Vs...>::value)> {};
 | 
			
		||||
 | 
			
		||||
template<Depth V>
 | 
			
		||||
struct MaxImpl<V>: std::integral_constant<decltype(V), V> {};
 | 
			
		||||
 | 
			
		||||
template<Depth... Vs>
 | 
			
		||||
constexpr Depth Max = MaxImpl<Vs...>::value;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user