thesis version
This commit is contained in:
17877
inc/catch.hpp
Normal file
17877
inc/catch.hpp
Normal file
File diff suppressed because it is too large
Load Diff
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