C ++模板运算符编译错误 [英] C++ template operator compilation error

查看:143
本文介绍了C ++模板运算符编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让一个类似于 std :: ostream 的C ++类,它将输入并写入两个 std :: ostream 在构造函数中给出。这里它与适当的运算符<< 模板一起:

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


template< class T>
const SplitStream&运算符<< (const SplitStream& sp,const T& x)
{
sp.a< X;
sp.b << X;
return sp;
}

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

  void foo(SplitStream& out)
{
double some_double = 1.23;
out<< bar< some_double< std :: endl;
}

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



<$ c $ p> ...错误C2678:二进制'<':无操作符,它接受类型为const SplitStream的左手操作数没有可接受的转换)...

我做错了什么?我试图定义运算符<< 没有consts,它也没有编译。

解决方案

现在的问题是 std :: endl 一个对象但是一个函数模板声明如下:

  template< typename cT,typename Traits> 
std :: basic_ostream< cT,Traits>& endl(std :: basic_ostream< cT,Traits>&);

要使用这样的函数指针,需要推导模板参数。为此, std :: basic_ostream< cT,Traits> 类声明了运算符 c >:

  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>&))

这样,编译器可以推导出 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 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!\\\
;
}


I'm trying to make a C++ class resembling std::ostream, that will take its input and write to two std::ostreams given in the constructor. Here it is together with appropriate operator<< template:

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;
}

Several lines below that code, I try to use this class:

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

And I get this rather enigmatic error:

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

What am I doing wrong? I tried to define operator<< without consts, and it didn't compile either.

解决方案

The immediate problem is that std::endl isn't an object but a function template declared something like this:

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& endl(std::basic_ostream<cT, Traits>&);

To use a function pointer like this, the template arguments need to be deduced. To this end, the class std::basic_ostream<cT, Traits> declared suitable overloads for 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>&));

This way, the compiler can deduce the correct instantiation when the std::endl function is referenced.

However, all that is utterly irrelevant because what you are trying to do is better done entirely differently! You should create a suitable stream buffer and use a reasonably constructed std::ostream with this custom stream buffer. Below is a complete example how to do it properly (I had posted it before but only a couple dozens times...):

#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";
}

这篇关于C ++模板运算符编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆