为了账号安全,请及时绑定邮箱和手机立即绑定

当重载operator <<时,std :: endl是未知类型

当重载operator <<时,std :: endl是未知类型

C++
qq_笑_17 2019-08-08 16:06:17
当重载operator <<时,std :: endl是未知类型我重载了运算符<<template <Typename T>UIStream& operator<<(const T);UIStream my_stream;my_stream << 10 << " heads";工作但是:my_stream << endl;给出编译错误:错误C2678:二进制'<<':找不到哪个运算符带有'UIStream'类型的左操作数(或者没有可接受的转换)做my_stream << endl工作的工作是什么?
查看完整描述

3 回答

?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

std::endl是一个函数,std::cout通过实现operator<<获取具有相同签名的函数指针来利用它std::endl

在那里,它调用函数,并转发返回值。

这是一个代码示例:

#include <iostream>struct MyStream{
    template <typename T>
    MyStream& operator<<(const T& x)
    {
        std::cout << x;

        return *this;
    }


    // function that takes a custom stream, and returns it
    typedef MyStream& (*MyStreamManipulator)(MyStream&);

    // take in a function with the custom signature
    MyStream& operator<<(MyStreamManipulator manip)
    {
        // call the function, and return it's value
        return manip(*this);
    }

    // define the custom endl for this stream.
    // note how it matches the `MyStreamManipulator`
    // function signature
    static MyStream& endl(MyStream& stream)
    {
        // print a new line
        std::cout << std::endl;

        // do other stuff with the stream
        // std::cout, for example, will flush the stream
        stream << "Called MyStream::endl!" << std::endl;

        return stream;
    }

    // this is the type of std::cout
    typedef std::basic_ostream<char, std::char_traits<char> > CoutType;

    // this is the function signature of std::endl
    typedef CoutType& (*StandardEndLine)(CoutType&);

    // define an operator<< to take in std::endl
    MyStream& operator<<(StandardEndLine manip)
    {
        // call the function, but we cannot return it's value
        manip(std::cout);

        return *this;
    }};int main(void){
    MyStream stream;

    stream << 10 << " faces.";
    stream << MyStream::endl;
    stream << std::endl;

    return 0;}

希望这能让您更好地了解这些事情是如何运作的。


查看完整回答
反对 回复 2019-08-08
?
白板的微信

TA贡献1883条经验 获得超3个赞

问题是这std::endl是一个功能模板,就像你的运营商一样<< 。所以当你写:

my_stream << endl;

你会希望编译器为运算符推导出模板参数endl。这是不可能的。

因此,您必须编写额外的非模板,操作符重载<<以使用操纵器。他们的原型看起来像:

UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));

(还有另外两个,替换std::ostreamstd::basic_ios<char>和 std::ios_base,如果你想允许所有的操纵器你也必须提供),它们的实现将与你的模板非常相似。实际上,如此相似,您可以使用您的模板进行实现,如下所示:

typedef std::ostream& (*ostream_manipulator)(std::ostream&);UIStream& operator<<(UIStream& os, ostream_manipulator pf){
   return operator<< <ostream_manipulator> (os, pf);}

最后一点,通常是编写自定义streambuf通常是一种更好的方法来实现应用于您正在使用的技术。


查看完整回答
反对 回复 2019-08-08
  • 3 回答
  • 0 关注
  • 930 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信