#ifndef UTIL_H #define UTIL_H #include #include #include #include #include namespace util{ namespace ranges = std::ranges; namespace views = std::ranges::views; //util template // find the most strong type, template struct _strong_type{}; template struct _strong_type{ using type = T; }; template struct _strong_type{ using type = decltype(true ? std::declval() : std::declval()); }; template struct _strong_type{ using type = typename _strong_type::type>::type; }; template using _strong_type_t = typename _strong_type::type; //can type T convert to Args... template struct _is_castable{}; template struct _is_castable{ static constexpr bool value = true; using type = T; }; template struct _is_castable{ using __true = char; using __false = struct {char _[2];}; static consteval __true __test(U); static consteval __false __test(...); static constexpr bool value = sizeof(__test(std::declval())) == sizeof(__true); using type = std::conditional; }; template struct _is_castable{ static constexpr bool value = _is_castable::type>::value; using type = std::conditional; }; template using _is_castable_v = _is_castable::value; //type can convert to const char*, char* std::string, std::string_view; template concept _support_string = requires{ _is_castable::value; }; //util function template<_support_string T> std::vector split_str(T str, T d){ auto view = views::split(str, d) | views::transform([](auto word){return std::string_view{word.begin(), word.end()};}); return std::vector{view.begin(), view.end()}; }; template<_support_string T> char* to_char(T str){ if constexpr (std::is_same_v || std::is_same_v){ return const_cast(str); } if constexpr (std::is_same_v){ return const_cast(str.c_str()); } if constexpr (std::is_same_v){ return const_cast(str.data()); } } }; #endif