Write a simple Function that works like “std::cout” but adds a Line Break at the End

百般思念 提交于 2019-12-08 10:13:29

问题


In C++ there is a standard library function called cout, which lets me send text to the console. I am sure you know that.

#include <iostream>
using std::cout;
cout << "Some Text " << 15 << " Other Text";

To do a linebreak at the end, I need to use endl.

cout << "Some Text " << 15 << " Other Text" << endl;

How can I write a function named coutl which behaves like cout but also adds a likebreak? I want to use the same syntax that cout uses, especially the << operator.

coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak

回答1:


By creating a little proxy object which adds << endl in its destructor:

class AddEndl
{
public:
  AddEndl(std::ostream& os) : _holder(new Holder(os)) {}

  template <class T>
  friend std::ostream& operator<< (const AddEndl& l, const T& t)
  {
    return (l._holder->_os) << t;
  }

private:
  struct Holder {
    Holder (std::ostream& os) : _os(os) {}
    ~Holder () { _os << std::endl; }

    std::ostream& _os;
  };

  mutable std::shared_ptr<Holder> _holder;
}

Then you need a function so that you will get a temporary:

AddEndl wrap(std::ostream& os)
{
  return AddEndl(os);
}

This should then work:

wrap(std::cout) << "Hello";

UPDATE:

I move the destructor which adds a std::endl to an inner object owned by a std::shared_ptr<> so that the example doesn't depend on Copy Elision anymore.




回答2:


Not possible with just a non-temp object created on the stack & which has full function scope. How will the object ever know what this is the last of the chained calls to the << operator?

You can try hacks like these

class coutl
{
    public:
    ~coutl()
    {
        cout<<endl;
    }

    template<class T>
    coutl &operator<<(const T &x)
    {
        cout<<x;
        return *this;
    }

};

int main()
{
    coutl()<<"Hello"<<10<<"World";
    coutl()<<"Hello"<<20<<"World";
}

Another similar hack using the destructor

class myostream
{
    public:
    ~myostream()
    {
        cout<<endl;
    }

    template<class T>
    myostream &operator<<(const T &x)
    {
        cout<<x;
        return *this;
    }

};

int main()
{
    {
        myostream coutl;
        coutl<<"Hello"<<10<<"World";
    }

    {
        myostream coutl;
        coutl<<"Hello"<<10<<"World";
    }

}



回答3:


In fact the code

cout << "Some Text " << 15 << " Other Text" << endl;

calls the operator function(s)

// (pseudo code)
std::ostream& operator<<(std::ostream, [type] obj);

several times for each use of the << operators. To achieve what you want you would need to create a class that behaves like std::ostream, but 'magically' knows when the 'last' call to operator<< is issued and appends a linebreak. That's not possible IMHO without another object that keeps track of the statements scope.




回答4:


coutl << "Some Text " << 15 << " Other Text"; // coutl should add a linebreak

Your idea can't be realize. In fact, cout << str1; is equivalent to cout.operator<<(str1) which returns a reference of cout itself. So cout << a << b << c; can be resolvd to ((cout << a) << b) << c; It doesn't know when is the last call to insert an linebreak.



来源:https://stackoverflow.com/questions/12987860/write-a-simple-function-that-works-like-stdcout-but-adds-a-line-break-at-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!