用于简单记录器的 << 运算符的可变参数模板
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_);
}
};
你能帮我解决以下问题吗?
我正在尝试使用可变参数模板和包扩展来编写记录器。问题是我知道 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_);
}
};