alsk/src/alsk/skeleton/traits.h

82 lines
1.9 KiB
C++

#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