C++模板运算符编译错误

KCH*_*KCH 4 c++ templates operators visual-studio-2010

我正在尝试使C++类类似 std::ostream,它将输入并写入std::ostream构造函数中给出的两个s.这里它与适当的operator<<模板一起:

struct SplitStream
{
    SplitStream(std::ostream & a_, std::ostream & b_) : a(a_), b(b_) {}
    std::ostream & a, & b;
};


template<class T>
const SplitStream & operator << (const SplitStream & sp, const T & x)
{
    sp.a << x;
    sp.b << x;
    return sp;
}
Run Code Online (Sandbox Code Playgroud)

这段代码下面有几行,我尝试使用这个类:

void foo(SplitStream & out)
{
    double some_double = 1.23;
    out << "bar" << some_double << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个相当神秘的错误:

... error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'const SplitStream' (or there is no acceptable conversion) ...
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我试图定义operator<<没有consts,它也没有编译.

Die*_*ühl 5

当前的问题是,std::endl它不是一个对象,而是一个声明如下的函数模板:

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& endl(std::basic_ostream<cT, Traits>&);
Run Code Online (Sandbox Code Playgroud)

要使用这样的函数指针,需要推导出模板参数.为此,该类std::basic_ostream<cT, Traits>声明了适合的重载operator<<():

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& std::baisic_ostream<cT, Traits>::operator<< (
    std::basic_ostream<cT, Traits>& (*manip)(std::basic_ostream<cT, Traits>&));
Run Code Online (Sandbox Code Playgroud)

这样,编译器可以在std::endl引用函数时推导出正确的实例化.

然而,所有这一切都完全无关紧要,因为你要做的事情完全不同!您应该创建一个合适的流缓冲区,并使用合理构造的std::ostream自定义流缓冲区.下面是一个完整的例子,如何正确地做到这一点(我以前发过它但只有几十次......):

#include <streambuf>

struct teebuf
    : std::streambuf
{
    std::streambuf* sb1_;
    std::streambuf* sb2_;

    teebuf(std::streambuf* sb1, std::streambuf* sb2)
        : sb1_(sb1), sb2_(sb2) {
    }
    int overflow(int c) {
        typedef std::streambuf::traits_type traits;
        bool rc(true);
        if (!traits::eq_int_type(traits::eof(), c)) {
            traits::eq_int_type(this->sb1_->sputc(c), traits::eof())
                && (rc = false);
            traits::eq_int_type(this->sb2_->sputc(c), traits::eof())
                && (rc = false);
        }
        return rc? traits::not_eof(c): traits::eof();
    }
    int sync() {
        bool rc(true);
        this->sb1_->pubsync() != -1 || (rc = false);
        this->sb2_->pubsync() != -1 || (rc = false);
        return rc? 0: -1;
    }
};

#include <fstream>
#include <iostream>

int main()
{
    std::ofstream fout("tee.txt");
    teebuf        sbuf(fout.rdbuf(), std::cout.rdbuf());
    std::ostream  out(&sbuf);
    out << "hello, world!\n";
}
Run Code Online (Sandbox Code Playgroud)