C ++模板运算符编译错误 [英] C++ template operator compilation error
问题描述
我试图让一个类似于 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::ostream
s 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屋!