thesis version

This commit is contained in:
2021-05-10 18:14:13 +02:00
commit b688da651b
191 changed files with 35833 additions and 0 deletions

17877
inc/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

7
inc/tmp/algorithm.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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