当要格式化的字段非常多时,格式化串中的{}也会非常多,如果{}中需要带修饰,则修饰的位置和字段的位置必须要正确匹配,下面的示例只包含10个字段,实际项目中的字段可能会达到50个以上,这就导致{}和字段要正确匹配这个工作靠人肉配对时会非常痛苦,如果字段还会经常增删,那问题就更严重;
userinfo u;
fmt::format(
"{},{},{},{.2f},{},{},{},{},{},{}"
, u.id
, u.name
, u.age
, u.height
, u.city
, u.x
, u.y
, u.z
, u.parent
, u.mother
);
此时格式化串{}和字段是成对出现的,无论有多少字段,无论是否经常增删,写代码时都会非常轻松
userinfo u;
xformat(
"{}", u.id
"{}", u.name
"{}", u.age
"{.2f}", u.height
"{}", u.city
"{}", u.x
"{}", u.y
"{}", u.z
"{}", u.parent
"{}", u.mother
);
#include
#include
template<class AllFmt, class Tuple, class FmtStr, class T, class... Args>
auto xformat_cat(AllFmt& allfmt, Tuple&& tup, FmtStr&& fmtstr, T&& val, Args&&... args)
{
allfmt += std::forward<FmtStr>(fmtstr);
if constexpr (sizeof...(Args))
{
return xformat_cat(allfmt,
std::tuple_cat(std::forward<Tuple>(tup), std::tuple(std::forward<T>(val))),
std::forward<Args>(args)...);
}
else
{
return std::tuple_cat(std::forward<Tuple>(tup), std::tuple(std::forward<T>(val)));
}
}
template<class CharT, class Tuple, std::size_t... I>
auto xformat_do(std::basic_string<CharT>& allfmt, Tuple&& tup, std::index_sequence<I...>)
{
if constexpr (std::is_same_v<CharT, wchar_t>)
{
return fmt::vformat(fmt::wstring_view(allfmt),
fmt::make_wformat_args(std::get<I>(std::forward<Tuple>(tup))...));
}
else
{
return fmt::vformat(allfmt,
fmt::make_format_args(std::get<I>(std::forward<Tuple>(tup))...));
}
}
template<class CharT, class Tuple>
auto xformat_do(std::basic_string<CharT>& allfmt, Tuple&& tup)
{
return xformat_do(allfmt, std::forward<Tuple>(tup),
std::make_index_sequence<std::tuple_size_v<std::remove_cv_t<std::remove_reference_t<Tuple>>>>{});
}
template<class FmtStr, class T, class... Args>
auto xformat(FmtStr&& fmtstr, T&& val, Args&&... args)
{
if constexpr (sizeof...(Args))
{
auto allfmt = asio2::to_basic_string(std::forward<FmtStr>(fmtstr));
return xformat_do(allfmt, xformat_cat(allfmt,
std::tuple(std::forward<T>(val)), std::forward<Args>(args)...));
}
else
{
return fmt::format(std::forward<FmtStr>(fmtstr), std::forward<T>(val));
}
}
int main()
{
std::string s1 = "abc", s2 = "def";
std::wstring ws1 = L"abc", ws2 = L"def";
std::cout << xformat("{}", std::move(s1), "{}", std::move(s2)) << std::endl;
std::wcout << xformat(L"{}", std::move(ws1), L"{}", std::move(ws2)) << std::endl;
while (std::getchar() != '\n');
return 0;
}