【发布时间】:2008-11-14 16:22:50
【问题描述】:
原始问题
我正在编写一个日志类,目标是能够做到这一点:
// thread one
Logger() << "Some string" << std::ios::hex << 45;
// thread two
Logger() << L"Some wide string" << std::endl;
目前我的 Logger 标头看起来像这样:
#pragma once;
#include <ostream>
class Logger
{
public:
Logger();
~Logger();
std::ostream* out_stream;
};
template <typename T>
Logger& operator<< (Logger& logger, T thing) {
*logger.out_stream << thing;
return logger;
}
关于这门课的一些注意事项:
- 跨平台兼容性不是问题。
- 在 Logger.cpp 内部有一个单例类负责创建“真正的”ostream。
- Logger 构造函数和解构函数执行必要的单例锁定。
我有三个问题:
- 如何使 operator
- 如何让操作符
- 如何添加特化,以便如果 T 是 WCHAR* 或 std::wstring,它将在将其传递给 out_stream 之前将其转换为 char* 或 std::string? (我可以进行转换。在我的情况下,丢失高 unicode 字符不是问题。)
答案中学到的东西总结:
- 将模板放在朋友之前而不是之后。
- std::ios::hex 不是操纵器。 std::hex 是一个操纵器。
最终结果
#pragma once
#include <ostream>
#include <string>
std::string ConvertWstringToString(std::wstring wstr);
class Logger
{
public:
Logger();
~Logger();
template <typename T>
Logger& operator<< (T data) {
*out << data;
return *this;
}
Logger& operator<< (std::wstring data) {
return *this << ConvertWstringToString(data);
}
Logger& operator<< (const wchar_t* data) {
std::wstring str(data);
return *this << str;
}
private:
std::ostream* out;
};
【问题讨论】:
-
你的结果是错误的。不允许在类范围内进行特化 :) 只是重载它们(省略 template 部分)在 Adam 的回答中是必需的(在命名空间范围内专门化它们),否则(当时的普通运算符函数)不再是朋友。跨度>
-
有趣的是,它在那里与他们合作。但是,为了正确起见,我还是删除了它们。谢谢!
标签: c++ templates operator-overloading