thesis version
This commit is contained in:
51
inc/alsk/skeleton/bone/farm.h
Normal file
51
inc/alsk/skeleton/bone/farm.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_FARM_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_FARM_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename> struct Farm;
|
||||
|
||||
template<
|
||||
typename Signature,
|
||||
typename Task_, typename TaskLinks_
|
||||
>
|
||||
struct Farm<Signature, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
|
||||
using Task = Task_;
|
||||
using TaskLinks = TaskLinks_;
|
||||
|
||||
using Links = tmp::Pack<TaskLinks>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = tmp::Pack<>;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
Task task;
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<Farm> {
|
||||
static constexpr bool serial = false;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using Traverser = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
|
||||
return function(parDepth, skeleton, Traverser::execute(parDepth+1, skeleton.task, function, std::forward<T>(init)));
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&& skeleton) noexcept {
|
||||
return std::forward<Skeleton>(skeleton).n;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args, typename F>
|
||||
void skeletonTraversal(Farm<Args...> const& s, F&& f) {
|
||||
std::forward<F>(f)(s.task, s.n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
60
inc/alsk/skeleton/bone/farmsel.h
Normal file
60
inc/alsk/skeleton/bone/farmsel.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_FARMSEL_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_FARMSEL_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename, typename> struct FarmSel;
|
||||
|
||||
template<
|
||||
typename Signature,
|
||||
typename Task_, typename TaskLinks_,
|
||||
typename Select_, typename SelectLinks_
|
||||
>
|
||||
struct FarmSel<Signature, tmp::Pack<Task_, TaskLinks_>, tmp::Pack<Select_, SelectLinks_>>: SkeletonBase {
|
||||
using Task = Task_;
|
||||
using Select = Select_;
|
||||
using TaskLinks = TaskLinks_;
|
||||
using SelectLinks = SelectLinks_;
|
||||
|
||||
using Links = tmp::Pack<TaskLinks, SelectLinks>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = tmp::Pack<>;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
Task task;
|
||||
Select select;
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<FarmSel> {
|
||||
static constexpr bool serial = false;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
|
||||
using TraverserSelect = SkeletonTraversal<typename std::decay_t<Skeleton>::Select>;
|
||||
return function(parDepth, skeleton,
|
||||
TraverserTask::execute(parDepth+1, skeleton.task, function, std::forward<T>(init)),
|
||||
TraverserSelect::execute(parDepth, skeleton.select, function, std::forward<T>(init))
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&& skeleton) noexcept {
|
||||
return std::forward<Skeleton>(skeleton).n;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args, typename F>
|
||||
void skeletonTraversal(FarmSel<Args...> const& s, F f) {
|
||||
f(s.task, s.n);
|
||||
f(s.select, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
61
inc/alsk/skeleton/bone/itersel.h
Normal file
61
inc/alsk/skeleton/bone/itersel.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_ITERSEL_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_ITERSEL_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename, typename> struct IterSel;
|
||||
|
||||
template<
|
||||
typename Signature,
|
||||
typename Task_, typename TaskLinks_,
|
||||
typename Select_, typename SelectLinks_
|
||||
>
|
||||
struct IterSel<Signature, tmp::Pack<Task_, TaskLinks_>, tmp::Pack<Select_, SelectLinks_>>: SkeletonBase {
|
||||
using Task = Task_;
|
||||
using TaskLinks = TaskLinks_;
|
||||
|
||||
using Select = Select_;
|
||||
using SelectLinks = SelectLinks_;
|
||||
|
||||
using Links = tmp::Pack<TaskLinks, SelectLinks>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = tmp::Pack<>;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
Task task;
|
||||
Select select;
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<IterSel> {
|
||||
static constexpr bool serial = true;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
|
||||
using TraverserSelect = SkeletonTraversal<typename std::decay_t<Skeleton>::Select>;
|
||||
return function(parDepth, skeleton,
|
||||
TraverserTask::execute(parDepth, skeleton.task, function, std::forward<T>(init)),
|
||||
TraverserSelect::execute(parDepth, skeleton.select, function, std::forward<T>(init))
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args, typename F>
|
||||
void skeletonTraversal(IterSel<Args...> const& s, F f) {
|
||||
f(s.task, 1);
|
||||
f(s.select, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
51
inc/alsk/skeleton/bone/loop.h
Normal file
51
inc/alsk/skeleton/bone/loop.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_LOOP_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_LOOP_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename> struct Loop;
|
||||
|
||||
template<
|
||||
typename Signature,
|
||||
typename Task_, typename TaskLinks_
|
||||
>
|
||||
struct Loop<Signature, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
|
||||
using Task = Task_;
|
||||
using TaskLinks = TaskLinks_;
|
||||
|
||||
using Links = tmp::Pack<TaskLinks>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = void;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
Task task;
|
||||
std::size_t n;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<Loop> {
|
||||
static constexpr bool serial = true;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using Traverser = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
|
||||
return function(parDepth, skeleton, Traverser::execute(parDepth, skeleton.task, function, std::forward<T>(init)));
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args, typename F>
|
||||
void skeletonTraversal(Loop<Args...> const& s, F&& f) {
|
||||
std::forward<F>(f)(s.task, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
70
inc/alsk/skeleton/bone/serial.h
Normal file
70
inc/alsk/skeleton/bone/serial.h
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_SERIAL_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_SERIAL_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename...> struct Serial;
|
||||
|
||||
template<typename Signature, typename... FunTypes, typename... LinksTypes>
|
||||
struct Serial<Signature, tmp::Pack<FunTypes, LinksTypes>...>: SkeletonBase {
|
||||
using Links = tmp::Pack<LinksTypes...>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = tmp::Pack<>;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
using TasksP = tmp::Pack<FunTypes...>;
|
||||
using Tasks = std::tuple<FunTypes...>;
|
||||
|
||||
Tasks tasks;
|
||||
|
||||
template<std::size_t I>
|
||||
constexpr auto const& task() const noexcept { return std::get<I>(tasks); }
|
||||
template<std::size_t I>
|
||||
constexpr auto& task() noexcept { return std::get<I>(tasks); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<Serial> {
|
||||
static constexpr bool serial = true;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
auto indices = std::make_index_sequence<std::tuple_size<decltype(skeleton.tasks)>{}>();
|
||||
return _traverse(parDepth, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init), std::move(indices));
|
||||
}
|
||||
|
||||
template<typename Skeleton, typename F, typename T, std::size_t... Is>
|
||||
static constexpr decltype(auto) _traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init, std::index_sequence<Is...>) {
|
||||
using Traversers = tmp::Pack<
|
||||
SkeletonTraversal<std::tuple_element_t<Is, typename std::decay_t<Skeleton>::Tasks>>...
|
||||
>;
|
||||
return function(parDepth, skeleton, tmp::PackGet<Traversers, Is>::execute(parDepth, skeleton.template task<Is>(), function, init)...);
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename Tuple, typename F, std::size_t... indices>
|
||||
void skeletonTraversalSerial(Tuple const& tasks, F f, std::index_sequence<indices...>) {
|
||||
using Expander = int[];
|
||||
static_cast<void>(Expander{(f(std::get<indices>(tasks), 1), 0)...});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Signature, typename... Tasks, typename F>
|
||||
void skeletonTraversal(Serial<Signature, Tasks...> const& s, F&& f) {
|
||||
impl::skeletonTraversalSerial(s.tasks, std::forward<F>(f), std::make_index_sequence<sizeof...(Tasks)>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
63
inc/alsk/skeleton/bone/while.h
Normal file
63
inc/alsk/skeleton/bone/while.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_WHILE_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_WHILE_H
|
||||
|
||||
#include "../bonebase.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename, typename, typename> struct While;
|
||||
|
||||
template<
|
||||
typename Signature,
|
||||
typename Test_, typename TestLinks_,
|
||||
typename Task_, typename TaskLinks_
|
||||
>
|
||||
struct While<Signature, tmp::Pack<Test_, TestLinks_>, tmp::Pack<Task_, TaskLinks_>>: SkeletonBase {
|
||||
using Test = Test_;
|
||||
using TestLinks = TestLinks_;
|
||||
|
||||
using Task = Task_;
|
||||
using TaskLinks = TaskLinks_;
|
||||
|
||||
using Links = tmp::Pack<TestLinks_, TaskLinks_>;
|
||||
using PackP = tmp::Parameters<Signature>;
|
||||
using PackR = Returns<Links>;
|
||||
using PackX = tmp::Pack<>;
|
||||
using Packs = arg::Placeholders<PackP, PackR, PackX>;
|
||||
|
||||
Test test;
|
||||
Task task;
|
||||
|
||||
~While() noexcept {}; // -Winline
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SkeletonTraits<While> {
|
||||
static constexpr bool serial = true;
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static constexpr decltype(auto) traverse(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using TraverserTest = SkeletonTraversal<typename std::decay_t<Skeleton>::Test>;
|
||||
using TraverserTask = SkeletonTraversal<typename std::decay_t<Skeleton>::Task>;
|
||||
return function(parDepth,
|
||||
skeleton,
|
||||
TraverserTest::execute(parDepth, skeleton.task, function, std::forward<T>(init)),
|
||||
TraverserTask::execute(parDepth, skeleton.task, function, std::forward<T>(init))
|
||||
);
|
||||
}
|
||||
|
||||
template<typename Skeleton>
|
||||
static constexpr std::size_t parallelizability(Skeleton&&) noexcept {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args, typename F>
|
||||
void skeletonTraversal(While<Args...> const& s, F f) {
|
||||
f(s.test, 1);
|
||||
f(s.task, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
9
inc/alsk/skeleton/bonebase.h
Normal file
9
inc/alsk/skeleton/bonebase.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONEBASE_H
|
||||
#define ALSK_ALSK_SKELETON_BONEBASE_H
|
||||
|
||||
#include "skeletonbase.h"
|
||||
#include "traits.h"
|
||||
|
||||
#include "link/args.h"
|
||||
|
||||
#endif
|
11
inc/alsk/skeleton/bones.h
Normal file
11
inc/alsk/skeleton/bones.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_BONE_H
|
||||
#define ALSK_ALSK_SKELETON_BONE_H
|
||||
|
||||
#include "bone/farm.h"
|
||||
#include "bone/farmsel.h"
|
||||
#include "bone/itersel.h"
|
||||
#include "bone/loop.h"
|
||||
#include "bone/serial.h"
|
||||
#include "bone/while.h"
|
||||
|
||||
#endif
|
7
inc/alsk/skeleton/link/args.h
Normal file
7
inc/alsk/skeleton/link/args.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_H
|
||||
#define ALSK_ALSK_SKELETON_LINK_ARGS_H
|
||||
|
||||
#include "args/placeholders.h"
|
||||
#include "args/traits.h"
|
||||
|
||||
#endif
|
32
inc/alsk/skeleton/link/args/placeholders.h
Normal file
32
inc/alsk/skeleton/link/args/placeholders.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_PLACEHOLDERS_H
|
||||
#define ALSK_ALSK_SKELETON_LINK_ARGS_PLACEHOLDERS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <tmp/pack.h>
|
||||
|
||||
namespace alsk {
|
||||
namespace arg {
|
||||
|
||||
/**
|
||||
* @brief argument placeholder for parameters
|
||||
*/
|
||||
template<std::size_t I>
|
||||
struct P: std::integral_constant<std::size_t, I> {};
|
||||
|
||||
/**
|
||||
* @brief argument placeholder for returned values
|
||||
*/
|
||||
template<std::size_t I>
|
||||
struct R: std::integral_constant<std::size_t, I> {};
|
||||
|
||||
/**
|
||||
* @brief argument placeholder for contextual arguments
|
||||
*/
|
||||
template<std::size_t I>
|
||||
struct C: std::integral_constant<std::size_t, I> {};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
226
inc/alsk/skeleton/link/args/traits.h
Normal file
226
inc/alsk/skeleton/link/args/traits.h
Normal file
@ -0,0 +1,226 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H
|
||||
#define ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <tmp/pack.h>
|
||||
#include <tmp/traits.h>
|
||||
|
||||
#include "placeholders.h"
|
||||
|
||||
namespace alsk {
|
||||
namespace arg {
|
||||
|
||||
/**
|
||||
* @brief true if the given type is a placeholder for a parameter
|
||||
*/
|
||||
template<typename T> struct IsP: std::false_type {};
|
||||
template<std::size_t I> struct IsP<P<I>>: std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isP = IsP<T>::value;
|
||||
|
||||
/**
|
||||
* @brief true if the given type is a placeholder for a returned value
|
||||
*/
|
||||
template<typename T> struct IsR: std::false_type {};
|
||||
template<std::size_t I> struct IsR<R<I>>: std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isR = IsR<T>::value;
|
||||
|
||||
/**
|
||||
* @brief true if the given type is a placeholder for a contextual argument
|
||||
*/
|
||||
template<typename T> struct IsC: std::false_type {};
|
||||
template<std::size_t I> struct IsC<C<I>>: std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isC = IsC<T>::value;
|
||||
|
||||
/**
|
||||
* @brief placeholders group
|
||||
*/
|
||||
template<typename P_, typename R_, typename C_>
|
||||
struct Placeholders {
|
||||
using P = tmp::AsPack<std::decay_t<P_>>;
|
||||
using R = tmp::AsPack<std::decay_t<R_>>;
|
||||
using C = tmp::AsPack<std::decay_t<C_>>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief apply type mods from A to B
|
||||
*/
|
||||
template<typename, typename B>
|
||||
struct ApplyTypeModsImpl {
|
||||
using type = B; // TODO: std::decay_t<B>
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct ApplyTypeModsImpl<A const&, B> {
|
||||
using type = std::decay_t<B> const&;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
using ApplyTypeMods = typename ApplyTypeModsImpl<A, B>::type;
|
||||
|
||||
/**
|
||||
* @brief ArgType
|
||||
*/
|
||||
template<typename T, typename, typename=void>
|
||||
struct ArgTypeImpl {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename A, typename Placeholders>
|
||||
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isP<std::decay_t<A>>>> {
|
||||
using type = tmp::PackGet<typename Placeholders::P, std::decay_t<A>::value>;
|
||||
};
|
||||
|
||||
template<typename A, typename Placeholders>
|
||||
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isR<std::decay_t<A>>>> {
|
||||
using type = tmp::PackGet<typename Placeholders::R, std::decay_t<A>::value>;
|
||||
};
|
||||
|
||||
template<typename A, typename Placeholders>
|
||||
struct ArgTypeImpl<A, Placeholders, std::enable_if_t<arg::isC<std::decay_t<A>>>> {
|
||||
using type = tmp::PackGet<typename Placeholders::C, std::decay_t<A>::value>;
|
||||
};
|
||||
|
||||
template<typename T, typename Placeholders>
|
||||
using ArgType = typename ArgTypeImpl<T, Placeholders>::type;
|
||||
|
||||
/**
|
||||
* @brief ArgGet
|
||||
*/
|
||||
template<typename, typename=void> struct ArgGet;
|
||||
|
||||
template<>
|
||||
struct ArgGet<void> {
|
||||
template<typename P, typename R, typename C>
|
||||
static void get(P&&, R&&, C&&) {}
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct ArgGet<A, std::enable_if_t<arg::isP<std::decay_t<A>>>> {
|
||||
template<typename P, typename R, typename C>
|
||||
static auto get(P&& p, R&&, C&&)
|
||||
-> /*ApplyTypeMods<A,*/ // TODO: does not work
|
||||
ArgType<A, arg::Placeholders<P, tmp::Pack<>, tmp::Pack<>>>
|
||||
/*>*/ {
|
||||
return std::get<std::decay_t<A>::value>(std::forward<P>(p));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct ArgGet<A, std::enable_if_t<arg::isR<std::decay_t<A>>>> {
|
||||
template<typename P, typename R, typename C>
|
||||
static auto get(P&&, R&& r, C&&)
|
||||
-> ApplyTypeMods<A,
|
||||
ArgType<A, arg::Placeholders<tmp::Pack<>, R, tmp::Pack<>>>
|
||||
> {
|
||||
return std::get<std::decay_t<A>::value>(std::forward<R>(r));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct ArgGet<A, std::enable_if_t<arg::isC<std::decay_t<A>>>> {
|
||||
template<typename P, typename R, typename C>
|
||||
static auto get(P&&, R&&, C&& x)
|
||||
-> ApplyTypeMods<A,
|
||||
ArgType<A, arg::Placeholders<tmp::Pack<>, tmp::Pack<>, C>>
|
||||
> {
|
||||
return std::get<std::decay_t<A>::value>(std::forward<C>(x));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IsPlaceholder
|
||||
*/
|
||||
namespace impl {
|
||||
|
||||
template<typename A>
|
||||
struct IsPlaceholder:
|
||||
std::integral_constant<bool,
|
||||
arg::isP<std::decay_t<A>> or arg::isR<std::decay_t<A>> or arg::isC<std::decay_t<A>>
|
||||
> {};
|
||||
|
||||
template<typename A>
|
||||
constexpr bool isPlaceholder = IsPlaceholder<A>::value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ArgFilter
|
||||
*/
|
||||
template<typename, typename = void> struct ArgFilterImpl;
|
||||
|
||||
template<typename Ret, typename T, typename... Ts>
|
||||
struct ArgFilterImpl<Ret(T, Ts...), std::enable_if_t<impl::isPlaceholder<T>>> {
|
||||
using type = tmp::FunctionCat<Ret(T), typename ArgFilterImpl<Ret(Ts...)>::type>;
|
||||
};
|
||||
|
||||
template<typename Ret, typename T, typename... Ts>
|
||||
struct ArgFilterImpl<Ret(T, Ts...), std::enable_if_t<!impl::isPlaceholder<T>>> {
|
||||
using type = typename ArgFilterImpl<Ret(Ts...)>::type;
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct ArgFilterImpl<Ret()> {
|
||||
using type = Ret();
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
using ArgFilter = typename ArgFilterImpl<F>::type;
|
||||
|
||||
/**
|
||||
* @brief RealTypeImpl
|
||||
* @param T a type to solve
|
||||
* @param Placeholders the placeholders list
|
||||
*/
|
||||
template<typename T, typename Placeholders>
|
||||
struct RealTypeImpl {
|
||||
using type = ArgType<T, Placeholders>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief RealType
|
||||
* @param T a type to solve
|
||||
* @param Placeholders the placeholders list
|
||||
*/
|
||||
template<typename T, typename Placeholders>
|
||||
using RealType = typename RealTypeImpl<T, Placeholders>::type;
|
||||
|
||||
/**
|
||||
* @brief RealSignature
|
||||
*/
|
||||
template<typename, typename> struct RealSignatureImpl;
|
||||
|
||||
template<typename Ret, typename... Ps, typename Placeholders>
|
||||
struct RealSignatureImpl<Ret(Ps...), Placeholders> {
|
||||
// using type = Ret(*)(typename RealType<Ps, P, R>::type...); // issue with const& parameters
|
||||
using type = std::function<Ret(RealType<Ps, Placeholders>...)>;
|
||||
};
|
||||
|
||||
template<typename T, typename Placeholders>
|
||||
using RealSignature = typename RealSignatureImpl<T, Placeholders>::type;
|
||||
|
||||
/**
|
||||
* @brief Returns
|
||||
*/
|
||||
template<typename> struct ReturnsImpl;
|
||||
template<typename... Fs>
|
||||
struct ReturnsImpl<tmp::Pack<Fs...>> {
|
||||
using type = tmp::Pack<tmp::ReturnType<Fs>...>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using Returns = typename ReturnsImpl<T>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
52
inc/alsk/skeleton/link/link.h
Normal file
52
inc/alsk/skeleton/link/link.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_LINK_LINK_H
|
||||
#define ALSK_ALSK_SKELETON_LINK_LINK_H
|
||||
|
||||
#include <tmp/pack.h>
|
||||
|
||||
#include "args.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include "../struct/struct.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief hold the skeleton links
|
||||
*/
|
||||
template<template<typename...> class T, typename F, typename... Ts>
|
||||
using L = S<T, F, Ts...>;
|
||||
|
||||
namespace impl {
|
||||
|
||||
/**
|
||||
* Pack of return types from links
|
||||
*/
|
||||
template<typename...> struct LinksToReturnTypes;
|
||||
|
||||
template<typename R, typename... Params, typename... Ls>
|
||||
struct LinksToReturnTypes<R(Params...), Ls...> {
|
||||
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
|
||||
};
|
||||
|
||||
template<template<typename...> class Skel, typename R, typename... Params, typename... InnerLs, typename... Ls>
|
||||
struct LinksToReturnTypes<alsk::L<Skel, R(Params...), InnerLs...>, Ls...> {
|
||||
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
|
||||
};
|
||||
|
||||
template<template<typename...> class Skel, std::size_t I, typename... Params, typename... InnerLs, typename... Ls>
|
||||
struct LinksToReturnTypes<alsk::L<Skel, alsk::arg::R<I>(Params...), InnerLs...>, Ls...> {
|
||||
using rets = typename LinksToReturnTypes<InnerLs...>::type;
|
||||
using R = tmp::PackGet<rets, I>;
|
||||
using type = tmp::PackCat<tmp::Pack<R>, typename LinksToReturnTypes<Ls...>::type>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LinksToReturnTypes<> {
|
||||
using type = tmp::Pack<>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
inc/alsk/skeleton/link/utility.h
Normal file
27
inc/alsk/skeleton/link/utility.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_LINK_UTILITY_H
|
||||
#define ALSK_ALSK_SKELETON_LINK_UTILITY_H
|
||||
|
||||
#include "args.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
template<typename> struct AutoLinkSerialImpl;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct AutoLinkSerialImpl<R(Args...)> {
|
||||
template<typename> struct Helper;
|
||||
template<std::size_t... indices>
|
||||
struct Helper<std::index_sequence<indices...>> {
|
||||
using in = R(alsk::arg::P<indices>...);
|
||||
using out = alsk::arg::R<0>(Args...);
|
||||
};
|
||||
|
||||
using type = Helper<decltype(std::make_index_sequence<sizeof...(Args)>())>;
|
||||
};
|
||||
|
||||
template<typename Signature>
|
||||
using AutoLinkSerial = typename AutoLinkSerialImpl<Signature>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
50
inc/alsk/skeleton/muscle/muscle.h
Normal file
50
inc/alsk/skeleton/muscle/muscle.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_MUSCLE_MUSCLE_H
|
||||
#define ALSK_ALSK_SKELETON_MUSCLE_MUSCLE_H
|
||||
|
||||
#include <tmp/pack.h>
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief hold the functionoid type and its links
|
||||
*/
|
||||
template<typename Type, typename Links>
|
||||
using Fun = tmp::Pack<Type, Links>;
|
||||
|
||||
}
|
||||
|
||||
template<typename T, T> struct Fn;
|
||||
|
||||
template<typename R, typename... Ts, R(*F)(Ts...)>
|
||||
struct Fn<R(*)(Ts...), F> {
|
||||
using Signature = R(Ts...);
|
||||
constexpr R operator()(Ts... args) { return F(args...); }
|
||||
};
|
||||
|
||||
template<typename R, typename... Ts, R(&F)(Ts...)>
|
||||
struct Fn<R(&)(Ts...), F> {
|
||||
using Signature = R(Ts...);
|
||||
constexpr R operator()(Ts... args) { return F(args...); }
|
||||
};
|
||||
|
||||
#define FN(f) Fn<decltype(f)&, f>
|
||||
#define FN_OVERLOAD(T, f) Fn<T, f>
|
||||
|
||||
/** C++17
|
||||
* namespace impl {
|
||||
*
|
||||
* template<typename T, T> struct Fn;
|
||||
*
|
||||
* template<typename R, typename... Ts, R(*F)(Ts...)>
|
||||
* struct Fn<R(*)(Ts...), F> {
|
||||
* R operator()(Ts... args) { return F(args...); }
|
||||
* };
|
||||
*
|
||||
* }
|
||||
*
|
||||
* template<auto F>
|
||||
* using Fn = impl::Fn<decltype(F), F>;
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
11
inc/alsk/skeleton/skeleton.h
Normal file
11
inc/alsk/skeleton/skeleton.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_SKELETON_H
|
||||
#define ALSK_ALSK_SKELETON_SKELETON_H
|
||||
|
||||
#include "bones.h"
|
||||
#include "utility.h"
|
||||
|
||||
#include "link/link.h"
|
||||
#include "muscle/muscle.h"
|
||||
#include "struct/struct.h"
|
||||
|
||||
#endif
|
23
inc/alsk/skeleton/skeletonbase.h
Normal file
23
inc/alsk/skeleton/skeletonbase.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_SKELETONBASE_H
|
||||
#define ALSK_ALSK_SKELETON_SKELETONBASE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "tags.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
struct SkeletonBase {
|
||||
using IsSkeleton = tag::SkeletonTag;
|
||||
|
||||
constexpr SkeletonBase() noexcept {}
|
||||
~SkeletonBase() noexcept {}
|
||||
|
||||
std::size_t step = 0;
|
||||
|
||||
std::size_t parDepth = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
17
inc/alsk/skeleton/struct/struct.h
Normal file
17
inc/alsk/skeleton/struct/struct.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_STRUCT_STRUCT_H
|
||||
#define ALSK_ALSK_SKELETON_STRUCT_STRUCT_H
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief hold the skeleton structure
|
||||
*/
|
||||
template<template<typename...> class T, typename... Ts>
|
||||
struct S {
|
||||
template<typename... Params>
|
||||
using type = T<Params...>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
12
inc/alsk/skeleton/tags.h
Normal file
12
inc/alsk/skeleton/tags.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_TAGS_H
|
||||
#define ALSK_ALSK_SKELETON_TAGS_H
|
||||
|
||||
namespace alsk {
|
||||
namespace tag {
|
||||
|
||||
struct SkeletonTag {};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
81
inc/alsk/skeleton/traits.h
Normal file
81
inc/alsk/skeleton/traits.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_TRAITS_H
|
||||
#define ALSK_ALSK_SKELETON_TRAITS_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "tags.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/**
|
||||
* @brief true if the given type is a Skeleton
|
||||
*/
|
||||
template<typename T, typename = void>
|
||||
struct IsSkeleton: std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct IsSkeleton<T, std::enable_if_t<std::is_same<typename std::decay_t<T>::IsSkeleton, tag::SkeletonTag>{}>>: std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isSkeleton = IsSkeleton<T>::value;
|
||||
|
||||
|
||||
/**
|
||||
* @brief class to determine a skeleton traits
|
||||
* @param serial true if the skeleton cannot be run in parallel
|
||||
*/
|
||||
template<template<typename...> class S>
|
||||
struct SkeletonTraits {
|
||||
static constexpr bool serial = true;
|
||||
};
|
||||
|
||||
template<typename> struct SkeletonTraitsTImpl;
|
||||
|
||||
template<template<typename...> class S, typename... Ts>
|
||||
struct SkeletonTraitsTImpl<S<Ts...>> {
|
||||
using type = SkeletonTraits<S>;
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
using SkeletonTraitsT = typename SkeletonTraitsTImpl<std::decay_t<S>>::type;
|
||||
|
||||
/**
|
||||
* @brief function to dynamically traverse a skeleton tree
|
||||
*
|
||||
* by default, do nothing (typically muscle case)
|
||||
*/
|
||||
template<typename Muscle, typename F,
|
||||
std::enable_if_t<not isSkeleton<std::decay_t<Muscle>>>* = nullptr
|
||||
>
|
||||
void skeletonTraversal(Muscle&&, F&&) {}
|
||||
|
||||
/**
|
||||
* @brief template to specialize to implement a bone
|
||||
*/
|
||||
template<typename Skeleton, typename Tag, typename Executor, typename Context> struct Impl;
|
||||
|
||||
/**
|
||||
* @brief template to specialize to define how to traverse a bone
|
||||
*/
|
||||
template<typename Skeleton, typename=void>
|
||||
struct SkeletonTraversal;
|
||||
|
||||
/**
|
||||
* @brief returns steps between two instances of the skeleton
|
||||
*/
|
||||
template<typename Skeleton, std::enable_if_t<isSkeleton<Skeleton>>* = nullptr>
|
||||
constexpr std::size_t skeletonStep(Skeleton const& s) {
|
||||
return s.step;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns 0
|
||||
*/
|
||||
template<typename Skeleton, std::enable_if_t<not isSkeleton<Skeleton>>* = nullptr>
|
||||
constexpr std::size_t skeletonStep(Skeleton const&) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
247
inc/alsk/skeleton/utility.h
Normal file
247
inc/alsk/skeleton/utility.h
Normal file
@ -0,0 +1,247 @@
|
||||
#ifndef ALSK_ALSK_SKELETON_UTILITY_H
|
||||
#define ALSK_ALSK_SKELETON_UTILITY_H
|
||||
|
||||
#include <tmp/algorithm.h>
|
||||
#include <tmp/tree.h>
|
||||
|
||||
#include "link/link.h"
|
||||
#include "struct/struct.h"
|
||||
#include "muscle/muscle.h"
|
||||
#include "traits.h"
|
||||
|
||||
namespace alsk {
|
||||
|
||||
namespace impl {
|
||||
|
||||
/**
|
||||
* Build inner skeletons
|
||||
*/
|
||||
template<typename, typename, typename, typename, typename> struct BuildSkeletonParts;
|
||||
|
||||
template<
|
||||
template<typename...> class Skel, typename... Ss,
|
||||
typename R, typename... Params, typename... Ls,
|
||||
typename PParams, typename RParams, typename XParams
|
||||
>
|
||||
struct BuildSkeletonParts<alsk::S<Skel, Ss...>, alsk::L<Skel, R(Params...), Ls...>, PParams, RParams, XParams> {
|
||||
using Placeholders = arg::Placeholders<PParams, RParams, XParams>;
|
||||
|
||||
using prms = tmp::Pack<RealType<Params, Placeholders>...>;
|
||||
using rets = typename LinksToReturnTypes<Ls...>::type;
|
||||
using xprm = tmp::Pack<>;
|
||||
using type = alsk::Fun<
|
||||
Skel<
|
||||
R(RealType<Params, Placeholders>...),
|
||||
typename BuildSkeletonParts<Ss, Ls, prms, rets, xprm>::type...
|
||||
>,
|
||||
RealType<R, arg::Placeholders<tmp::Pack<>, rets, xprm>>(Params...)
|
||||
>;
|
||||
};
|
||||
|
||||
template<typename S, typename L, typename, typename, typename>
|
||||
struct BuildSkeletonParts {
|
||||
using type = alsk::Fun<S, L>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build outer skeleton
|
||||
*/
|
||||
template<typename, typename> struct BuildSkeleton;
|
||||
|
||||
template<template<typename...> class Skel, typename... Ss, typename R, typename... Params, typename... Ls>
|
||||
struct BuildSkeleton<alsk::S<Skel, Ss...>, alsk::L<Skel, R(Params...), Ls...>> {
|
||||
using rets = typename LinksToReturnTypes<Ls...>::type;
|
||||
using xprm = tmp::Pack<>;
|
||||
using type = Skel<
|
||||
R(Params...),
|
||||
typename BuildSkeletonParts<Ss, Ls, tmp::Pack<Params...>, rets, xprm>::type...
|
||||
>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a skeleton from its structure and its links
|
||||
*/
|
||||
template<typename S, typename L>
|
||||
using BuildSkeletonT = typename impl::BuildSkeleton<S, L>::type;
|
||||
|
||||
template<template<typename...> class S, template<typename...> class L>
|
||||
struct BuildSkeleton {
|
||||
template<typename, typename> struct Type;
|
||||
|
||||
template<typename... SParams, typename... LParams>
|
||||
struct Type<tmp::Pack<SParams...>, tmp::Pack<LParams...>> {
|
||||
using type = BuildSkeletonT<S<SParams...>, L<LParams...>>;
|
||||
};
|
||||
|
||||
template<typename SParams, typename LParams>
|
||||
using type = typename Type<SParams, LParams>::type;
|
||||
|
||||
template<typename SParams, typename LParams>
|
||||
using skeleton = typename Type<SParams, LParams>::type;
|
||||
};
|
||||
|
||||
// is it possible?
|
||||
// template<template<typename...> class S, template<typename...> class L>
|
||||
// template<typename SParams, typename LParams>
|
||||
// using type = typename BuildSkeleton<S, L>::type<SParams, LParams>;
|
||||
|
||||
template<template<typename...> class Skeleton, typename S, typename L = S>
|
||||
struct Branch {
|
||||
template<typename... Ts>
|
||||
using skeleton = Skeleton<Ts...>;
|
||||
using signature = S;
|
||||
using links = L;
|
||||
};
|
||||
|
||||
template<typename T, typename L>
|
||||
struct Leaf {
|
||||
using type = T;
|
||||
using links = L;
|
||||
};
|
||||
|
||||
/**
|
||||
* TreeFromSkeleton
|
||||
*/
|
||||
template<typename, typename=void> struct TreeFromSkeletonImpl;
|
||||
|
||||
template<template<typename...> class Skeleton, typename S, typename... Ps>
|
||||
struct TreeFromSkeletonImpl<Skeleton<S, Ps...>, std::enable_if_t<isSkeleton<Skeleton<S, Ps...>>>> {
|
||||
using type = tmp::Tree<Branch<Skeleton, S, S>, typename TreeFromSkeletonImpl<Ps>::type...>;
|
||||
};
|
||||
|
||||
template<template<typename...> class Skeleton, typename S, typename... Ps, typename L>
|
||||
struct TreeFromSkeletonImpl<Fun<Skeleton<S, Ps...>, L>, std::enable_if_t<isSkeleton<Skeleton<S, Ps...>>>> {
|
||||
using type = tmp::Tree<Branch<Skeleton, S, L>, typename TreeFromSkeletonImpl<Ps>::type...>;
|
||||
};
|
||||
|
||||
template<typename T, typename L>
|
||||
struct TreeFromSkeletonImpl<Fun<T, L>, std::enable_if_t<not isSkeleton<T>>> {
|
||||
using type = tmp::Tree<Leaf<T, L>>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using TreeFromSkeleton = typename TreeFromSkeletonImpl<T>::type;
|
||||
|
||||
/**
|
||||
* SkeletonFromTree
|
||||
*/
|
||||
template<typename> struct SkeletonFromTreeImpl;
|
||||
|
||||
template<template<typename...> class Skeleton, typename S, typename L, typename... Cs>
|
||||
struct SkeletonFromTreeImpl<tmp::Tree<Branch<Skeleton, S, L>, Cs...>> {
|
||||
using type = Skeleton<S, typename SkeletonFromTreeImpl<Cs>::fun...>;
|
||||
using fun = Fun<type, L>;
|
||||
};
|
||||
|
||||
template<typename T, typename L, typename... Cs>
|
||||
struct SkeletonFromTreeImpl<tmp::Tree<Leaf<T, L>, Cs...>> {
|
||||
using type = T;
|
||||
using fun = Fun<type, L>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using SkeletonFromTree = typename SkeletonFromTreeImpl<T>::type;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<typename> struct GetTemplate;
|
||||
|
||||
template<template<typename...> class TT, typename... Ps>
|
||||
struct GetTemplate<TT<Ps...>> {
|
||||
template<typename... As>
|
||||
using tmpl = TT<As...>;
|
||||
};
|
||||
|
||||
template<template<typename...> class Skel, typename... Skargs>
|
||||
struct SkeletonTraversal<Skel<Skargs...>, std::enable_if_t<isSkeleton<Skel<Skargs...>>>> {
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static decltype(auto) execute(std::size_t parDepth, Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using Traits = SkeletonTraits<Skel>;
|
||||
return Traits::traverse(parDepth, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init));
|
||||
}
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static decltype(auto) execute(Skeleton&& skeleton, F&& function, T&& init) {
|
||||
using Traits = SkeletonTraits<Skel>;
|
||||
return Traits::traverse(0, std::forward<Skeleton>(skeleton), std::forward<F>(function), std::forward<T>(init));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
struct SkeletonTraversal<S, std::enable_if_t<not isSkeleton<S>>> {
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static T execute(std::size_t, Skeleton&&, F&&, T&& init) { return init; }
|
||||
|
||||
template<typename Skeleton, typename F, typename T>
|
||||
static T execute(Skeleton&&, F&&, T&& init) { return init; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace alsk {
|
||||
|
||||
/*
|
||||
template<typename S>
|
||||
struct SkeletonParallelHeightImpl {
|
||||
template<typename> struct CheckParallelityImpl;
|
||||
template<template<typename...> class Skel, typename Sign, typename Link>
|
||||
struct CheckParallelityImpl<Branch<Skel, Sign, Link>> {
|
||||
using type = std::integral_constant<bool, not SkeletonTraits<Skel>::serial>;
|
||||
};
|
||||
template<typename T, typename Link>
|
||||
struct CheckParallelityImpl<Leaf<T, Link>> {
|
||||
using type = std::integral_constant<bool, false>;
|
||||
};
|
||||
template<typename P>
|
||||
using CheckParallelity = typename CheckParallelityImpl<P>::type;
|
||||
template<typename P>
|
||||
using CheckParallelityEach = tmp::Transform<P, CheckParallelity>;
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
using Sum = std::integral_constant<decltype(LHS::value), LHS::value + RHS::value>;
|
||||
|
||||
template<typename P>
|
||||
using SumEach = tmp::Accumulate<P, Sum, std::integral_constant<tmp::Depth, 0>>;
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
using Max = std::integral_constant<decltype(LHS::value), (LHS::value>RHS::value)? LHS::value:RHS::value>;
|
||||
|
||||
using tree = TreeFromSkeleton<S>;
|
||||
using rtlpaths = tmp::TreeAllRTLPaths<tree>;
|
||||
using parallel = tmp::Transform<rtlpaths, CheckParallelityEach>;
|
||||
using parallelc = tmp::Transform<parallel, SumEach>;
|
||||
using result = tmp::Accumulate<parallelc, Max, std::integral_constant<tmp::Depth, 0>>;
|
||||
|
||||
static constexpr tmp::Depth value = result::value;
|
||||
};
|
||||
/*/
|
||||
template<typename S>
|
||||
struct SkeletonParallelHeightImpl {
|
||||
template<typename, typename...> struct CalcHeightImpl;
|
||||
template<template<typename...> class Skel, typename Sign, typename Link, typename... Ts>
|
||||
struct CalcHeightImpl<Branch<Skel, Sign, Link>, Ts...> {
|
||||
static constexpr tmp::Depth par = SkeletonTraits<Skel>::serial? 0:1;
|
||||
using type = std::integral_constant<tmp::Depth, par + tmp::detail::Max<Ts::type::value...>>;
|
||||
};
|
||||
template<typename T, typename Link, typename... Ts>
|
||||
struct CalcHeightImpl<Leaf<T, Link>, Ts...> {
|
||||
using type = std::integral_constant<tmp::Depth, 0>;
|
||||
};
|
||||
template<typename P, typename... Ts>
|
||||
using CalcHeight = typename CalcHeightImpl<P, Ts...>::type;
|
||||
using CalcHeightDefault = std::integral_constant<tmp::Depth, 0>;
|
||||
|
||||
using tree = TreeFromSkeleton<S>;
|
||||
static constexpr tmp::Depth value = tmp::TreeAccumulate<tree, CalcHeight, CalcHeightDefault>::value;
|
||||
};
|
||||
//*/
|
||||
|
||||
template<typename S>
|
||||
constexpr tmp::Depth skeletonParallelHeight = SkeletonParallelHeightImpl<S>::value;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user