#ifndef ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H #define ALSK_ALSK_SKELETON_LINK_ARGS_TRAITS_H #include #include #include #include #include #include "placeholders.h" namespace alsk { namespace arg { /** * @brief true if the given type is a placeholder for a parameter */ template struct IsP: std::false_type {}; template struct IsP>: std::true_type {}; template constexpr bool isP = IsP::value; /** * @brief true if the given type is a placeholder for a returned value */ template struct IsR: std::false_type {}; template struct IsR>: std::true_type {}; template constexpr bool isR = IsR::value; /** * @brief true if the given type is a placeholder for a contextual argument */ template struct IsC: std::false_type {}; template struct IsC>: std::true_type {}; template constexpr bool isC = IsC::value; /** * @brief placeholders group */ template struct Placeholders { using P = tmp::AsPack>; using R = tmp::AsPack>; using C = tmp::AsPack>; }; } /** * @brief apply type mods from A to B */ template struct ApplyTypeModsImpl { using type = B; // TODO: std::decay_t }; template struct ApplyTypeModsImpl { using type = std::decay_t const&; }; template using ApplyTypeMods = typename ApplyTypeModsImpl::type; /** * @brief ArgType */ template struct ArgTypeImpl { using type = T; }; template struct ArgTypeImpl>>> { using type = tmp::PackGet::value>; }; template struct ArgTypeImpl>>> { using type = tmp::PackGet::value>; }; template struct ArgTypeImpl>>> { using type = tmp::PackGet::value>; }; template using ArgType = typename ArgTypeImpl::type; /** * @brief ArgGet */ template struct ArgGet; template<> struct ArgGet { template static void get(P&&, R&&, C&&) {} }; template struct ArgGet>>> { template static auto get(P&& p, R&&, C&&) -> /*ApplyTypeMods, tmp::Pack<>>> /*>*/ { return std::get::value>(std::forward

(p)); } }; template struct ArgGet>>> { template static auto get(P&&, R&& r, C&&) -> ApplyTypeMods, R, tmp::Pack<>>> > { return std::get::value>(std::forward(r)); } }; template struct ArgGet>>> { template static auto get(P&&, R&&, C&& x) -> ApplyTypeMods, tmp::Pack<>, C>> > { return std::get::value>(std::forward(x)); } }; /** * @brief IsPlaceholder */ namespace impl { template struct IsPlaceholder: std::integral_constant> or arg::isR> or arg::isC> > {}; template constexpr bool isPlaceholder = IsPlaceholder::value; } /** * @brief ArgFilter */ template struct ArgFilterImpl; template struct ArgFilterImpl>> { using type = tmp::FunctionCat::type>; }; template struct ArgFilterImpl>> { using type = typename ArgFilterImpl::type; }; template struct ArgFilterImpl { using type = Ret(); }; template using ArgFilter = typename ArgFilterImpl::type; /** * @brief RealTypeImpl * @param T a type to solve * @param Placeholders the placeholders list */ template struct RealTypeImpl { using type = ArgType; }; /** * @brief RealType * @param T a type to solve * @param Placeholders the placeholders list */ template using RealType = typename RealTypeImpl::type; /** * @brief RealSignature */ template struct RealSignatureImpl; template struct RealSignatureImpl { // using type = Ret(*)(typename RealType::type...); // issue with const& parameters using type = std::function...)>; }; template using RealSignature = typename RealSignatureImpl::type; /** * @brief Returns */ template struct ReturnsImpl; template struct ReturnsImpl> { using type = tmp::Pack...>; }; template using Returns = typename ReturnsImpl::type; } #endif