首页 > 解决方案 > 可变成员函数参数包扩展

问题描述

我需要帮助来向 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 增强功能。

标签: c++c++14variadic-templatesvariadic-functionstemplate-meta-programming

解决方案


不确定你到底想要什么,但是......我想是这样的(注意:代码未经测试)

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), ... ); }

推荐阅读