未完成….
pre
std::format
需要一个format_string
,样例如下:https://en.cppreference.com/w/cpp/utility/format/format1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template<typename... Args>
std::string dyna_print(std::string_view rt_fmt_str, Args&&... args)
{
return std::vformat(rt_fmt_str, std::make_format_args(args...));
}
int main()
{
std::cout << std::format("Hello {}!\n", "world");
std::string fmt;
for (int i{}; i != 3; ++i)
{
fmt += "{} "; // constructs the formatting string
std::cout << fmt << " : ";
std::cout << dyna_print(fmt, "alpha", 'Z', 3.14, "unused");
std::cout << '\n';
}
}Output:
1
2
3
4Hello world!
{} : alpha
{} {} : alpha Z
{} {} {} : alpha Z 3.14习惯
std::cout
写法的会觉得{}
是额外多的东西如果想在老代码使用
std::format
就很为难,如果改的话要改很多,不能很好的兼容老代码老代码的两种写法:
1
2
3// string-stream
std::stringstream ss;
ss << 123 << "abc" << 1.9 << '\n';1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37// easy-string wrap
template<typename _Func, typename..._Args>
static void _inner_unpak(_Func fun, const _Args&... args)
{
(void)std::initializer_list<int>{
[&](const auto& arg)
{
fun(arg);
return 0;
}(args)...
};
}
template<typename..._Args>
inline static void _inner_format(std::ostream& stream, const _Args&... args)
{
_inner_unpak([&](const auto& arg) {
stream << arg;
}, args...);
}
template<typename... _Args>
inline static std::string inner_string(const _Args&... args)
{
std::stringstream ss;
(void)std::initializer_list<int>{
[&](const auto& arg)
{
ss << arg;
return 0;
}(args)...
};
//_inner_format(ss, args...);
return ss.str();
}
inner_string("abc ", 123, " ", 1.9, '\n');因为
inner_string
是我后面常用的方式,就想在这个基础上把std::stringstream
修改为std::format
step by step
- 通过模版推导出需要多少个
{}
1
2
3
4template<typename... args_tt>
void test_function(args_tt&&... args) {
constexpr std::size_t args_size = sizeof...(args);
} - 构造一个 format-string
1
2
3
4
5
6
7
8
9
10
11
12std::string generate_placeholders(std::size_t count) {
std::string placeholders;
placeholders.reserve(count * 3);
for (std::size_t i = 0; i < count; ++i) {
placeholders += '{';
placeholders += '}';
if (i < count_vv - 1) {
placeholders += ' ';
}
}
return placeholders;
} - 至此已经可以使用了:
1
2
3
4
5
6
7
8
9
10
11template<typename... Args>
std::string format_string(const Args&... args) {
std::size_t arg_count = sizeof...(args);
std::string placeholders = generate_placeholders(arg_count);
return std::vformat(placeholders, std::make_format_args(args...));
}
format_string("abc", 123); // 得到:abc 123
std::format("{} {}", "abc", 123); // 得到:abc 123 - 但是这里有个比较严重的问题:相比
std::format("{} {}", "abc", 123);
,generate_placeholders
的过程是个O(n)
复杂度的多余的动作