227 lines
5.6 KiB
C
227 lines
5.6 KiB
C
|
#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
|