forked from OctaForge/libostd
remove ostd::to_string and ostd::concat (both replaced by more flexible format)
This commit is contained in:
parent
1e1f6d63a2
commit
a23a42da1f
|
@ -869,6 +869,16 @@ inline auto citer(T const &r) -> decltype(ranged_traits<T const>::iter(r)) {
|
|||
return ranged_traits<T const>::iter(r);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
static std::true_type test_iterable(decltype(ostd::iter(std::declval<T>())) *);
|
||||
template<typename>
|
||||
static std::false_type test_iterable(...);
|
||||
|
||||
template<typename T>
|
||||
constexpr bool iterable_test = decltype(test_iterable<T>(0))::value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct half_range: input_range<half_range<T>> {
|
||||
using range_category = range_category_t <typename T::range>;
|
||||
|
|
247
ostd/string.hh
247
ostd/string.hh
|
@ -431,253 +431,6 @@ inline namespace string_literals {
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: redesign this */
|
||||
template<typename R, typename T, typename F>
|
||||
R &&concat(R &&sink, T const &v, string_range sep, F func) {
|
||||
auto range = ostd::iter(v);
|
||||
if (range.empty()) {
|
||||
return std::forward<R>(sink);
|
||||
}
|
||||
for (;;) {
|
||||
using VT = decltype(func(range.front()));
|
||||
static_assert(
|
||||
std::is_convertible_v<VT, string_range> ||
|
||||
std::is_convertible_v<VT, char>,
|
||||
"range value must be convertible to string range or char"
|
||||
);
|
||||
if constexpr(std::is_convertible_v<VT, string_range>) {
|
||||
range_put_all(sink, string_range{func(range.front())});
|
||||
} else {
|
||||
sink.put(func(range.front()));
|
||||
}
|
||||
range.pop_front();
|
||||
if (range.empty()) {
|
||||
break;
|
||||
}
|
||||
range_put_all(sink, sep);
|
||||
}
|
||||
return std::forward<R>(sink);
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
R &&concat(R &&sink, T const &v, string_range sep = " ") {
|
||||
auto range = ostd::iter(v);
|
||||
if (range.empty()) {
|
||||
return std::forward<R>(sink);
|
||||
}
|
||||
for (;;) {
|
||||
string_range ret = range.front();
|
||||
range_put_all(sink, ret);
|
||||
range.pop_front();
|
||||
if (range.empty()) {
|
||||
break;
|
||||
}
|
||||
range_put_all(sink, sep);
|
||||
}
|
||||
return std::forward<R>(sink);
|
||||
}
|
||||
|
||||
template<typename R, typename T, typename F>
|
||||
R &&concat(R &&sink, std::initializer_list<T> v, string_range sep, F func) {
|
||||
return concat(sink, ostd::iter(v), sep, func);
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
R &&concat(R &&sink, std::initializer_list<T> v, string_range sep = " ") {
|
||||
return concat(sink, ostd::iter(v), sep);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename T, typename R>
|
||||
static std::true_type test_stringify(
|
||||
decltype(std::declval<T const &>().to_string(std::declval<R &>())) *
|
||||
);
|
||||
|
||||
template<typename, typename>
|
||||
static std::false_type test_stringify(...);
|
||||
|
||||
template<typename T, typename R>
|
||||
constexpr bool stringify_test = decltype(test_stringify<T, R>(0))::value;
|
||||
|
||||
template<typename T>
|
||||
static std::true_type test_iterable(decltype(ostd::iter(std::declval<T>())) *);
|
||||
template<typename>
|
||||
static std::false_type test_iterable(...);
|
||||
|
||||
template<typename T>
|
||||
constexpr bool iterable_test = decltype(test_iterable<T>(0))::value;
|
||||
}
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct to_string;
|
||||
|
||||
template<typename T>
|
||||
struct to_string<T, std::enable_if_t<detail::iterable_test<T>>> {
|
||||
std::string operator()(T const &v) const {
|
||||
std::string ret("{");
|
||||
auto x = appender_range<std::string>{};
|
||||
concat(x, ostd::iter(v), ", ", to_string<
|
||||
std::remove_const_t<std::remove_reference_t<
|
||||
range_reference_t<decltype(ostd::iter(v))>
|
||||
>>
|
||||
>());
|
||||
ret += x.get();
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct to_string<T, std::enable_if_t<
|
||||
detail::stringify_test<T, appender_range<std::string>>
|
||||
>> {
|
||||
std::string operator()(T const &v) const {
|
||||
auto app = appender<std::string>();
|
||||
if (!v.to_string(app)) {
|
||||
return std::string{};
|
||||
}
|
||||
return std::move(app.get());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<bool> {
|
||||
std::string operator()(bool b) {
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<char> {
|
||||
std::string operator()(char c) {
|
||||
std::string ret;
|
||||
ret += c;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#define OSTD_TOSTR_NUM(T) \
|
||||
template<> \
|
||||
struct to_string<T> { \
|
||||
std::string operator()(T v) { \
|
||||
return std::to_string(v); \
|
||||
} \
|
||||
};
|
||||
|
||||
OSTD_TOSTR_NUM(sbyte)
|
||||
OSTD_TOSTR_NUM(short)
|
||||
OSTD_TOSTR_NUM(int)
|
||||
OSTD_TOSTR_NUM(long)
|
||||
OSTD_TOSTR_NUM(float)
|
||||
OSTD_TOSTR_NUM(double)
|
||||
|
||||
OSTD_TOSTR_NUM(byte)
|
||||
OSTD_TOSTR_NUM(ushort)
|
||||
OSTD_TOSTR_NUM(uint)
|
||||
OSTD_TOSTR_NUM(ulong)
|
||||
OSTD_TOSTR_NUM(llong)
|
||||
OSTD_TOSTR_NUM(ullong)
|
||||
OSTD_TOSTR_NUM(ldouble)
|
||||
|
||||
#undef OSTD_TOSTR_NUM
|
||||
|
||||
template<typename T>
|
||||
struct to_string<T *> {
|
||||
std::string operator()(T *v) {
|
||||
char buf[16];
|
||||
sprintf(buf, "%p", v);
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<char const *> {
|
||||
std::string operator()(char const *s) {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<char *> {
|
||||
std::string operator()(char *s) {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<std::string> {
|
||||
std::string operator()(std::string const &s) {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<char_range> {
|
||||
std::string operator()(char_range const &s) {
|
||||
return std::string{s};
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_string<string_range> {
|
||||
std::string operator()(string_range const &s) {
|
||||
return std::string{s};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct to_string<std::pair<T, U>> {
|
||||
std::string operator()(std::pair<T, U> const &v) {
|
||||
std::string ret{"{"};
|
||||
ret += to_string<std::remove_cv_t<std::remove_reference_t<T>>>()(v.first);
|
||||
ret += ", ";
|
||||
ret += to_string<std::remove_cv_t<std::remove_reference_t<U>>>()(v.second);
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<size_t I, size_t N>
|
||||
struct tuple_to_str {
|
||||
template<typename T>
|
||||
static void append(std::string &ret, T const &tup) {
|
||||
ret += ", ";
|
||||
ret += to_string<std::remove_cv_t<std::remove_reference_t<
|
||||
decltype(std::get<I>(tup))
|
||||
>>>()(std::get<I>(tup));
|
||||
tuple_to_str<I + 1, N>::append(ret, tup);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct tuple_to_str<N, N> {
|
||||
template<typename T>
|
||||
static void append(std::string &, T const &) {}
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct tuple_to_str<0, N> {
|
||||
template<typename T>
|
||||
static void append(std::string &ret, T const &tup) {
|
||||
ret += to_string<std::remove_cv_t<std::remove_reference_t<
|
||||
decltype(std::get<0>(tup))
|
||||
>>>()(std::get<0>(tup));
|
||||
tuple_to_str<1, N>::append(ret, tup);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ...T>
|
||||
struct to_string<std::tuple<T...>> {
|
||||
std::string operator()(std::tuple<T...> const &v) {
|
||||
std::string ret("{");
|
||||
detail::tuple_to_str<0, sizeof...(T)>::append(ret, v);
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct temp_c_string {
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue