C/C++自定义std::format格式化
C++
#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iomanip>
template <class T0, class T1, class = void>
struct _has_stream_bit_shl : std::false_type {};
template <class T0, class T1>
struct _has_stream_bit_shl<T0, T1, std::void_t<decltype(
std::declval<T0>() << std::declval<T1>()
)>> : std::true_type {};
template <class T, class = void>
struct _has_range_begin_end : std::false_type {};
template <class T>
struct _has_range_begin_end<T, std::void_t<decltype(
std::begin(std::declval<T>()) != std::end(std::declval<T>())
)>> : std::true_type {};
template <class T, class = void>
struct _has_tuple_size : std::false_type {};
template <class T>
struct _has_tuple_size<T, std::void_t<decltype(
std::tuple_size<T>::value
)>> : std::true_type {};
struct _to_stream_impl {
template <class Os, class T, std::size_t ...Is>
static void _helper_tuple_to_stream(Os& os, T const& t, std::string_view fms, std::index_sequence<Is...>) {
os << '(';
(to_stream(os, std::get<0>(t), fms), ..., (os << ' ', to_stream(os, std::get<Is + 1>(t), fms)));
os << ')';
}
template <class Os, class T, std::enable_if_t<!_has_stream_bit_shl<Os&, T const&>::value
&& (std::tuple_size<T>::value >= 1), int> = 0>
static void to_stream(Os& os, T const& t, std::string_view fms) {
return _helper_tuple_to_stream(os, t, fms, std::make_index_sequence<std::tuple_size_v<T> -1>{});
}
template <class Os, class T>
static auto to_stream(Os& os, T const& t, std::string_view fms) -> decltype((std::enable_if_t<!_has_stream_bit_shl<Os&, T const&>::value && !_has_range_begin_end<T>::value, void>)(std::declval<T&>()[0], std::declval<T&>().length())) {
os << "[glm: ";
for (int i = 0; i < t.length(); ++i) {
to_stream(os, t[i], fms);
os << ", ";
}
os << "]";
}
template <class Os, class T, std::enable_if_t<!_has_stream_bit_shl<Os&, T const&>::value
&& (std::tuple_size<T>::value == 0), int> = 0>
static void to_stream(Os& os, T const& t, std::string_view fms) {
os << "()";
}
template <class Os, class T, std::enable_if_t<!_has_stream_bit_shl<Os&, T const&>::value
&& !_has_tuple_size<T>::value&& _has_range_begin_end<T>::value, int> = 0>
static void to_stream(Os& os, T const& t, std::string_view fms) {
auto it = std::begin(t);
auto eit = std::end(t);
os << '[';
if (it != eit) {
to_stream(os, *it, fms);
++it;
for (; it != eit; ++it) {
os << ' ';
to_stream(os, *it, fms);
}
}
os << ']';
}
template <class Os, class T, std::enable_if_t<_has_stream_bit_shl<Os&, T const&>::value && !std::is_enum<T>::value, int> = 0>
static void to_stream(Os& os, T const& t, std::string_view fms) {
auto flgs = os.flags();
if (fms.size() != 0) {
if (fms.size() != 0 && fms[0] == '-') {
fms = fms.substr(1);
os << std::right;
}
if (fms.size() != 0 && fms[0] == '0') {
fms = fms.substr(1);
os << std::setfill('0');
}
{
int tmp = 0;
while (fms.size() != 0 && '0' <= fms[0] && '9' >= fms[0]) {
tmp *= 10;
tmp += fms[0] - '0';
fms = fms.substr(1);
}
if (tmp != 0)
os << std::setw(tmp);
}
if (fms.size() != 0 && fms[0] == '.') {
fms = fms.substr(1);
int tmp = 0;
while (fms.size() != 0 && '0' <= fms[0] && '9' >= fms[0]) {
tmp *= 10;
tmp += fms[0] - '0';
fms = fms.substr(1);
}
os << std::setprecision(tmp);
}
if (fms.size() != 0) {
switch (fms[0]) {
case 'x': os << std::hex; break;
case 'd': os << std::dec; break;
case 'o': os << std::oct; break;
};
}
}
os << t;
os.flags(flgs);
}
template <class Os, class T, std::enable_if_t<std::is_enum<T>::value
&& _has_stream_bit_shl<Os&, typename std::underlying_type<T>::type const&>::value, int> = 0>
static void to_stream(Os& os, T const& t, std::string_view fms) {
os << std::underlying_type_t<T>{t};
}
};
template <class Os, class T>
void to_stream(Os& os, T const& t, std::string_view fms) {
_to_stream_impl::to_stream(os, t, fms);
}
template <class T>
std::string to_string(T const& t, std::string_view fms) {
std::ostringstream ss;
to_stream(ss, t, fms);
return ss.str();
}
template <class T>
std::string to_string(T const& t) {
if constexpr (std::is_convertible_v<T, std::string>) {
return t;
}
else {
std::ostringstream ss;
to_stream(ss, t, {});
return ss.str();
}
}
template <int curr, class Os, class It, class ...Args>
bool __format(Os& os, It fb, It fe, std::tuple<Args const &...> const& args) {
if constexpr (curr >= sizeof...(Args)) {
if (fb != fe)
os << std::string_view(fb, fe - fb);
return curr > sizeof...(Args);
}
else {
if (fb == fe) return false;
auto ib = std::find(fb, fe, '{');
if (ib == fe) return false;
os << std::string_view(fb, ib - fb);
++ib;
auto ie = std::find(ib, fe, '}');
if (ie == fe) return false;
++ie;
auto fms = std::string_view(ib, ie - ib);
if (auto i = fms.find(':'); i != std::string_view::npos) {
fms = fms.substr(i + 1);
}
to_stream(os, std::get<curr>(args), fms);
return __format<curr + 1>(os, ie, fe, args);
}
}
template <class Os, class ...Args>
bool format_to(Os& os, std::string_view fmt, Args const &...args) {
return __format<0>(os, fmt.data(), fmt.data() + fmt.size(), std::tuple<Args const &...>(args...));
}
template <class ...Args>
std::string format(std::string_view fmt, Args const &...args) {
std::stringstream ss;
format_to(ss, fmt, args...);
return ss.str();
}
void test() {
std::cout << format("add({}+{})={}\n", 1, 2, 3);
}
C
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stdarg.h>
#include <string>
template <class ...Ts>
std::string cformat(const char *fmt, Ts &&...ts) {
int n = snprintf(nullptr, 0, fmt, std::forward<Ts>(ts)...);
if (n < 0) return {};
std::string res;
res.resize(n + 2);
n = snprintf(res.data(), n + 1, fmt, std::forward<Ts>(ts)...);
res.resize(n);
return res;
}
输出: add(1+2)=3
创作不易,小小的支持一下吧!
原文地址:https://blog.csdn.net/qq_30220519/article/details/140332972
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!