的std :: ostream的::运营商LT;<没有为std :: string定义?

时间:2012-09-14 12:47:55

标签: c++ std stdstring ostream

我偶然发现了一个我无法理解的错误。

我认为它基本上归结为这个错误:

 error: no matching function for call to ‘std::basic_ostream<char>::operator<<(const std::basic_string<char>&)’

我查看了www.cplusplus.com的规范,实际上它说std::ostream::operator<<没有std::string作为参数的定义。

我的问题是,当一个人写std_ostream_instance << std_fancy_string;时会发生什么。我认为这是std::out << std::string("Hello world!")旁边最常见的调用之一(例如const char*)。

错误源自以下几行:

template<typename T> 
void Log::_log(const T& msg)
{  _sink->operator<<( msg ); }

_sink被视为std::ostream* 有一些包装功能,但它在这里打破。

我想我可以通过编写

来解决
template<> 
void Log::_log<std::string>(const std::string& msg) {
  _sink->operator<<( msg.c_str() );
}

因为默认情况下定义了ostream& operator<< (ostream& out, const unsigned char* s );

我认为没有理由不自动猜测它,因为它显然可以像cout << any_std_string一样使用。

不确定这是否相关但我希望能够通过我的日志函数向下传递std::ostream以外的任何内容。我使用了显式的非模板化声明,但决定转移到log(const T& anything_to_log)的模板来重新设计它。拥有5+超载似乎很愚蠢。当我尝试编译类似Log::log( std::string("test case") )的内容时,我收到错误。

它看起来像一些愚蠢的简单但我不能靠自己得到它。试图谷歌和搜索堆栈无济于事。

关于,luk32。

PS。我检查了解决方法并且它有效。为什么没有隐含地完成?

2 个答案:

答案 0 :(得分:9)

operator <<重载不是ostream的成员。它们是独立的功能,例如

ostream& operator << ( ostream& out, const basic_string<T>& bs );

尝试

template<typename T> 
void Log::_log(const T& msg)
{  *_sink << msg;  }

答案 1 :(得分:5)

std::string版本不是成员函数,因此无法作为_sink的成员进行调用。尝试这种方式来获取成员和非成员版本(事实上,你根本不需要成员版本):

#include <iostream>
#include <string>

int main()
{
    std::ostream * os = &std::cout;
    std::string s = "Hello\n";

    // This will not work
    // os->operator<<(s);
    (*os) << s;

    return 0;
}

或者更好的方法是将_sink存储为参考,并按照通常的方式输出cout