用于简单记录器的 << 运算符的可变参数模板

variadic template for << operator for simple logger

你能帮我解决以下问题吗? 我正在尝试使用可变参数模板和包扩展来编写记录器。问题是我知道 operator<< 必须只接受两个参数 - 第二个参数然后变成一个完整的包,我不知道如何将 'const Args& ...rest' 扩展为 'const T& v, const Args& ...rest' 任何大师都可以解释如何重写可变参数表达式来实现这个目标吗?最终游戏是拥有如下代码: log << "string" << 1 << 1.2;

同时打印。 (请原谅 cout,它只是为了示例目的。想法是收集 oss_ 中的所有参数,然后打印一次。)。 编译器当前抱怨,我的理解是 operator<< 只接受两个参数的问题。

‘LogHandle& operator<<(LogHandle&, const T&, const Args& ...)’ must take exactly two argument

代码如下:

 #include <iostream>
   #include <string>
   #include <sstream>

    class LogHandle {
        public:
        template<typename T>
        friend LogHandle& operator<<(LogHandle& l, const T& v)
        {
            l.oss_ << v;
            std::cout << "Value is: " << l.oss_.str().c_str();
            l.oss_.str("");
            l.oss_.clear();
            return l;
        }

        template<typename T, typename... Args>
        friend LogHandle& operator<<(LogHandle& l, const T& v, const Args&... rest)
        {
            l.oss_ << v << " ";
            return l << (rest...);
        }

        std::ostringstream oss_;
    };

    int main(int, char**)
    {  
        LogHandle log;
        log << "String" << 1;
    }

你想做的事情不可能完全按照你想要的方式进行,因为运算符的数量是固定的——你不能让它们可变。

但是,您可以改为使用从 operator << 返回的代理到 "collect" 一个地方的所有参数。像这样:

class LogHandle
{
    template<typename T>
    friend LogProxy operator<<(LogHandle& l, const T& v)
    {
        LogProxy p(*this);
        p << v;
        return p;
    }

    void print(const std::ostringstream &oss)
    {
       std::cout << "Value is: " << oss.str();
    }
};

struct LogProxy
{
  LogHandle *handle;
  std::ostringstream oss_;

  LogProxy(LogHandle &l) : handle(&l) {}

  LogProxy(LogProxy &&rhs) : handle(rhs.handle) { rhs.handle = nullptr; }

  template <class T>
  friend LogProxy& operator<< (LogProxy &p, const T &v)
  {
    p.oss_ << v;
    return p;
  }

  ~LogProxy()
  {
    if (handle) handle->print(oss_);
  }
};