c++ - 可变成员函数参数包扩展
问题描述
我需要帮助来向 c++14 类添加可变成员函数以支持日志记录。我的课程目前在 Windows 和另一个无法访问标准库的嵌入式操作系统上运行。我的代码中散布着数百个#ifdefs
如下所示的预处理器,我的目标是将这些块(其中许多具有多个参数)合并到一个常见的可变参数成员函数中,我可以boost::log
通过boost::format
(_WIN32) 或 (Embedded OS)登录) 到一个特殊gErrorLineLog
对象,该对象支持一些非常基本的类型(包括const char*
)的流插入,如运算符。将后一个对象视为类似于std::stringstream
.
#if defined (_WIN32)
LOG_ERROR(gLogger, gChannel) << boost::format("%1%")
% "'Transmit429Request' invalid message length";
#else
gErrorLineLog << "error: TX429 [bad message length]";
#endif
以下堆栈溢出答案boost::format 与可变参数模板参数对于回答如何将 windows/boost::format
端放入可变参数成员函数有很长的路要走,但我不知道如何循环嵌入案例的扩展包(我必须在我的可变参数模板函数中按照以下几行做一些事情:
for (auto next : parameterpack) {
gErrorLineLog << next:
}
编辑
到目前为止,我有一个嵌入式案例的部分解决方案(我没有 STL,因此没有 STL std::initializer_list<int>
) - 感谢 max66 提供的替代技巧,当我传入带有相关可变参数的记录器时,该技巧效果很好。
在看完 Jason Turner 的 C++ 每周视频第 4 集大约 70% 之后,他解释了与 c++14 兼容的参数包扩展背后的一些神秘魔力。我更喜欢使用折叠表达式(再次感谢 max66 提供了另一种更紧凑的折叠表达式语法),但不幸的是 gcc 5.3.0 没有 c++17,因此没有折叠表达式)。
我反馈后的最新版本如下:
template <typename LOGGER, typename ... Args>
void addLogEntry(LOGGER& VideoLogger, Args const& ... args)
{
#if defined (_WIN32)
LOG_INFO(gLogger, gChannel) << boost::format(
"DOUTRequest: query, eotw[0x%1%]")
% boost::io::group(std::setfill('0'),
std::hex, std::setw(4), *endOfFrame);
#else
// https://www.youtube.com/watch?v=VXi0AOQ0PF0
// parameter pack expansion using comma operator
VideoLogger.clear();
using unused = int[];
(void)unused{0, (VideoLogger << args, 0)...};
#endif
}
我在我的应用程序代码中调用它:
#if defined (_WIN32)
// I'm not sure how to get this right
LOG_INFO(gLogger, gChannel) << boost::format("received: TX429 with [%1%] labels") % numArincWords %
#else // THIS WORKS
addLogEntry(gReceiveLineLog,
"received: TX429 with [", dec,
numArincWords, "] labels");
#endif
如您所见,我还没有完全弄清楚如何在记录器或对记录器的调用中执行 win32 增强功能。
解决方案
不确定你到底想要什么,但是......我想是这样的(注意:代码未经测试)
template <typename ELLT, typename ... Args>
void errorLog (ELLT & gErrorLineLog, Args const & ... as)
{
using unused = int[];
(void)unused { 0, ((void)gErrorLineLog << as, 0)... };
}
如果你可以使用 C++17,也许只是
template <typename ELLT, typename ... Args>
void errorLog (ELLT & gErrorLineLog, Args const & ... as)
{ ( ((void)gErrorLineLog << as), ... ); }
推荐阅读
- android - JavaBinder:未捕获的远程异常!(跨进程还不支持异常?
- ibm-watson - 智能文档理解未按预期工作。BETA 版本有问题吗?
- hibernate - HQL 是否有等效于 SQL COVERT() 函数
- database - MongoDB索引可以根据某些属性是否为空对文档进行排序
- ios - UITableView 重新加载部分时的内容插入更改
- python - 如何使用随机空格分隔符拆分此字符串?
- node.js - Express Node js对路由中的模式对象进行排序
- docker - 我有两个容器在不同的不同端口运行如何为两个容器做 DNS 条目
- java - 如何使用附加的安全 CSV 文件向用户发送电子邮件,并且电子邮件不应回复
- amazon-web-services - 下载 SpaceNet 数据集:权限被拒绝