96 lines
2.8 KiB
C
96 lines
2.8 KiB
C
|
#ifndef UTIL_H
|
||
|
#define UTIL_H
|
||
|
|
||
|
#include <type_traits>
|
||
|
#include <string>
|
||
|
#include <string_view>
|
||
|
#include <vector>
|
||
|
#include <ranges>
|
||
|
|
||
|
namespace util{
|
||
|
namespace ranges = std::ranges;
|
||
|
namespace views = std::ranges::views;
|
||
|
|
||
|
//util template
|
||
|
|
||
|
// find the most strong type,
|
||
|
template<typename... Types>
|
||
|
struct _strong_type{};
|
||
|
|
||
|
template<typename T>
|
||
|
struct _strong_type<T>{
|
||
|
using type = T;
|
||
|
};
|
||
|
|
||
|
template<typename Ta, typename Tb>
|
||
|
struct _strong_type<Ta, Tb>{
|
||
|
using type = decltype(true ? std::declval<Ta>() : std::declval<Tb>());
|
||
|
};
|
||
|
|
||
|
template<typename T, typename... args>
|
||
|
struct _strong_type<T, args...>{
|
||
|
using type =
|
||
|
typename _strong_type<T, typename _strong_type<args...>::type>::type;
|
||
|
};
|
||
|
|
||
|
template<typename... args>
|
||
|
using _strong_type_t = typename _strong_type<args...>::type;
|
||
|
|
||
|
//can type T convert to Args...
|
||
|
template<typename... Types>
|
||
|
struct _is_castable{};
|
||
|
|
||
|
template<typename T>
|
||
|
struct _is_castable<T>{
|
||
|
static constexpr bool value = true;
|
||
|
using type = T;
|
||
|
};
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
struct _is_castable<T, U>{
|
||
|
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<T>())) == sizeof(__true);
|
||
|
using type = std::conditional<value, U, void>;
|
||
|
};
|
||
|
|
||
|
template<typename T, typename... args>
|
||
|
struct _is_castable<T, args...>{
|
||
|
static constexpr bool value = _is_castable<T, typename _is_castable<args...>::type>::value;
|
||
|
using type = std::conditional<value, T, void>;
|
||
|
};
|
||
|
|
||
|
template<typename... args>
|
||
|
using _is_castable_v = _is_castable<args...>::value;
|
||
|
|
||
|
//type can convert to const char*, char* std::string, std::string_view;
|
||
|
template<typename T>
|
||
|
concept _support_string = requires{
|
||
|
_is_castable<T, const char*, char*, std::string, std::string_view>::value;
|
||
|
};
|
||
|
|
||
|
//util function
|
||
|
template<_support_string T>
|
||
|
std::vector<std::string_view> 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<std::string_view>{view.begin(), view.end()};
|
||
|
};
|
||
|
|
||
|
template<_support_string T>
|
||
|
char* to_char(T str){
|
||
|
if constexpr (std::is_same_v<T, const char*> || std::is_same_v<T, char>){
|
||
|
return const_cast<char*>(str);
|
||
|
}
|
||
|
if constexpr (std::is_same_v<T, std::string>){
|
||
|
return const_cast<char*>(str.c_str());
|
||
|
}
|
||
|
if constexpr (std::is_same_v<T, std::string_view>){
|
||
|
return const_cast<char*>(str.data());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif
|