#pragma once /* * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BLT_META_H #define BLT_META_H #include #include #include #include namespace blt::meta { template, typename... IArgs> struct arg_helper { using First = IFirst; using Next = arg_helper; }; template struct arg_helper { using First = IFirst; using Next = void; }; template<> struct arg_helper<> { using First = void; using Next = void; }; template struct lambda_helper { using Lambda = TheLambda; }; template struct lambda_helper { using Lambda = TheLambda; using Return = IReturn; using Class = IClass; using Args = arg_helper; template explicit lambda_helper(T) {} lambda_helper() = default; }; template lambda_helper(Lambda) -> lambda_helper; // https://stackoverflow.com/questions/66397071/is-it-possible-to-check-if-overloaded-operator-for-type-or-class-exists template class is_streamable { private: template static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()) { return std::declval(); } template static auto test(...) -> std::false_type { return std::declval(); } public: static constexpr bool value = decltype(test(0))::value; }; template inline constexpr bool is_streamable_v = is_streamable::value; namespace detail { template struct value_type_helper { template inline static constexpr auto get(int) -> typename Subs::value_type { return std::declval(); } template inline static constexpr Or get(...) { return std::declval(); } }; template struct reference_type_helper { template inline static constexpr auto get(int) -> typename Subs::reference { return std::declval(); } template inline static constexpr Or get(...) { return std::declval(); } }; template struct const_reference_type_helper { template inline static constexpr auto get(int) -> typename Subs::const_reference { return std::declval(); } template inline static constexpr Or get(...) { return std::declval(); } }; template struct pointer_type_helper { template inline static constexpr auto get(int) -> typename Subs::pointer { return std::declval(); } template inline static constexpr Or get(...) { return std::declval(); } }; template struct difference_type_helper { template inline static constexpr auto get(int) -> typename Subs::difference_type { return std::declval(); } template inline static constexpr Or get(...) { return std::declval(); } }; } template using value_type_t = decltype(detail::value_type_helper::template get(0)); template using difference_t = decltype(detail::difference_type_helper::template get(0)); template using pointer_t = decltype(detail::pointer_type_helper::template get(0)); template using reference_t = decltype(detail::reference_type_helper::template get(0)); template using const_reference_t = decltype(detail::const_reference_type_helper::template get(0)); #define BLT_META_MAKE_FUNCTION_CHECK(FUNC, ...)\ template \ class has_func_##FUNC : public std::false_type \ {}; \ template \ class has_func_##FUNC().FUNC(,##__VA_ARGS__))>> : public std::true_type \ {}; \ template \ inline constexpr bool has_func_##FUNC##_v = has_func_##FUNC::value; #define BLT_META_MAKE_MEMBER_CHECK(MEMBER)\ template \ class has_member_##MEMBER : public std::false_type \ {}; \ template \ class has_member_##MEMBER> : public std::true_type \ {}; \ template \ inline constexpr bool has_member_##MEMBER##_v = has_member_##MEMBER::value; } #endif //BLT_GP_META_H