如何使用标头中定义的输出流运算符
How to use an output stream operator defined in a header
我希望能够将任何std::vector<T>
的内容附加到输出流中。我找到了这段代码:
#ifndef DEBUG_H_
#define DEBUG_H_
#include <vector>
template < class T >
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
os << "[";
for (typename std::vector<T>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
{
os << " " << *ii;
}
os << "]";
return os;
}
#endif /* DEBUG_H_ */
并放入标题Debug.h
.如何在项目中使用此运算符?
编辑:我已经验证了这在单元测试中有效:
#include "Debug.h"
TEST_F(AuxGTest, testVectorDebug) {
std::vector<int> vec(10, 42);
std::cout << "vec: " << vec << std::endl;
}
但是将其与log4cxx的日志语句一起使用不起作用:
#include <log4cxx>
#include "Debug.h"
namespace Foo {
class Bar {
void foo() {
std::vector<int> vec(10, 42);
DEBUG("vec: " << vec);
}
}
}
这将生成以下编译器消息:
/usr/local/Cellar/log4cxx/0.10.0/include/log4cxx/helpers/messagebuffer.h:190:47: error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'
你想在哪里使用它? 正如所宣称的,它在全球命名空间,因此除非 T
是类型,否则 ADL 不会找到它在全局命名空间中定义。 它不会被正常查找(如果位于全局命名空间以外的命名空间中(命名空间,并且该命名空间中有一个operator<<
(该命名空间会隐藏它(。 如果在 中调用,也找不到它一个模板,如果任何参数是依赖的,因为从属名称查找仅使用 ADL。
当然,除了玩具,你真的不想这样做。程序。 std::vector
的不同用途将需要不同的输出格式;最好将 std::vector
类中,并operator<<
定义类,用于每种不同的语义用法。 (对于玩具程序,您可以在命名空间std
中定义运算符。 未定义行为,但是由于没有其他人会看到代码,或者必须维护它,如果不维护它,这不是世界末日工作...
编辑:
由于您似乎将其用于某种跟踪或调试:这是有意义的一种情况支持std::vector
的统一输出,因为它用于输出内部状态。 另一方面,这很常见要包装ostream
的情况,如下所示:
class Logger
{
std::ostream* myDest;
public:
Logger( std::ostream* dest )
: myDest( dest )
{
}
template <typename T>
Logger& operator<<( T const& value )
{
if ( myDest != NULL ) {
*myDest << value;
}
return *this;
}
};
这允许日志记录的运行时配置(加上自动插入诸如__FILE__
和__LINE__
之类的内容,如果您使用一个宏来获取 Logger
的实例(;您的宏DEBUG
可能是这样的:
#define DEBUG getLogger( TRACELEVEL_DEBUG, __FILE__, __LINE__ )
其中getLogger
是一个返回Logger
的全局函数使用正确的ostream
初始化(或空指针,如果该级别的日志记录不处于活动状态(。 完成此操作后,您可以添加特殊功能,例如:
template <typename T>
Logger& Logger::operator<<( std::vector<T> const& value )
{
if ( myDest != NULL ) {
// your code here...
}
return *this;
}
由于其中一个参数,<<
运算符将是一个Logger
实例,ADL无论如何都会找到运算符。
关于 log4cxx 的用户定义运算符,也存在类似的问题。我通过建议将运算符放在 log4cxx::helpers
命名空间中来回答这个问题。看。
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 将异类初始值设定项列表传递给流运算符
- C++ 中完全自定义的流运算符
- 参数相关查找和流运算符重载
- 如何在C++中编写 ostream 的向量,它接收所有不同的输出流,如 cout、ostringstream 和 ofs
- 在输出流中插入换行符
- 在类外部重载输入和输出流
- 通用容器的输出流
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- C++ 输出流运算符 <<() 中的字符何时加宽?
- 编译器将输出的流运算符<<解释为用于按位左移的二进制运算符<<
- 如何为提升日志和自定义类型定义输出流运算符
- C++ 中的递增/递减和输出流运算符优先级
- 输出流中的运算符优先级C++
- 输出流运算符的重载
- 重载类的输出流运算符
- C++ 编译器选择输出流运算符<<的错误重载
- C++:输入和输出流运算符:关联性
- 如何使用标头中定义的输出流运算符