c++ knowledge
C++11 引入User-defined literals
在最近使用的两个github高赞库,fmt和nlohmann/json中,都看到了类似的用法。
- fmt中展示了
using namespace std::literals::chrono_literals
的用法,如使用24h
或者30min
后,可以转化成对应的时间长度,注意的是引入的c++版本是不同的:
d: C++20
h: C++14
min/ms: C++14
ns: C++14
s: C++14
us: C++14
y: C++14
- 用户把字符串转化成json对象,可以带上类似关键字
_json
,实现了std::string
到json
的转化,类似的写法如
nlohmann::json = R"(
{
"pi": 3.141,
"happy": true
}
)"_json;
C++11 引入String literal
注意到上面转换json字符串时前面的R,这是C++11 引入的字符串字面常量,意味着所见即所得。同时还有以下的字面常量
L"s-char-sequence(optional)": cosnt wchar_t[N]
u8"s-char-sequence(optional)": const char[N],C++11
u"s-char-sequence(optional)": const char16_t[N],C++11
U"s-char-sequence(optional)": const char32_t[N],C++11
prefix(optional) R"d-char-sequence(optional)(r-char-sequence(optional))d-char-sequence(optional)": C++11
一些库的使用
利用fmt进行更便捷的输出
开始使用fmt时,编译报undefined reference to fmt::v8::vprint
错误,尝试调整了C++编译的版本,还是报错,后来找到了两种解决方法
- 编译的时候链接fmt,做法是编译clone后的项目,会在
/usr/lib/
下生成libfmt.so
动态库,但这么操作显然不是很方便 - 在整个函数的开头声明#define FMT_HEADER_ONLY。考虑到使用的日志库spdlog也用了fmt,编译的标准也是C++11,解决的方法应该不是很麻烦。果然spdlog中也是声明了仅使用头文件
利用spdlog写入日志文件
跑了本地demo是可以写入文件的,但是利用xtest测试时,就无法写入,也是疑问了好长时间,上网一查,还是太年轻。
spdlog是有一个global register
的,用来管理日志对象,spdlog中每一个日志对象称为一个sinks
,用来向目标写入日志。所以一个程序可以有多个sinks
,向终端、文件等写入,每个sinks
可以设置写入日志的格式和等级等。
每个日志对象是自动注册的,但是也可以设置默认的日志对象,这样所有的日志均写入同一个对象。
但对于写入文件注意的是,如果程序提前终止,默认无法写入文件的,因为此时的日志内容在缓冲区,所以需要flush_on
,spdlog也可以支持定时刷新缓冲区
// 绑定多个sinks的日志对象
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_st>());
sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_st>("logfile", 23, 59));
auto combined_logger = std::make_shared<spdlog::logger>("name", begin(sinks), end(sinks));
//register it if you need to access it globally
spdlog::register_logger(combined_logger);
spdlog::set_default_logger(file_logger);
spdlog::drop("logger_name");
spdlog::drop_all();
// 设置输出缓存内容的日志等级
spdlog::flush_on(spdlog::level::info);
尽可能消除Warning
- 打印
size_t
时,%d
会出现警告,对于size_t
,对应着%zu
,而对于ssize_t
, 对应着%zd