0

在 C++ 中有一个名为 的标准库函数cout,它可以让我将文本发送到控制台。我相信你知道这一点。

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

最后要换行,我需要使用endl.

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

如何编写一个名为的函数coutl,它的行为类似于cout但也添加了一个likebreak?我想使用相同的语法cout,尤其是<<运算符。

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

4 回答 4

6

<< endl通过创建一个添加其析构函数的小代理对象:

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

然后你需要一个函数,这样你就会得到一个临时的:

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

这应该可以工作:

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

更新:

std::endl我移动了将 a 添加到 a 拥有的内部对象的析构函数,std::shared_ptr<>以便该示例不再依赖于 Copy Elision。

于 2012-10-20T11:26:17.880 回答
1

仅在堆栈上创建一个具有完整功能范围的非临时对象是不可能的。对象怎么会知道这是对 的最后一个链式调用<< operator

你可以尝试这样的黑客

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

使用析构函数的另一个类似 hack

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

}
于 2012-10-20T11:22:43.447 回答
0

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

你的想法无法实现。其实cout << str1;相当于cout.operator<<(str1)which返回了cout本身的一个引用。所以cout << a << b << c;可以解决 ((cout << a) << b) << c;它不知道最后一次调用插入换行符是什么时候。

于 2012-10-20T14:26:32.983 回答
0

其实代码

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

调用操作员函数

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

操作员每次使用几次<<。要实现您想要的,您需要创建一个行为类似于 的类std::ostream,但“神奇地”知道何时operator<<发出“最后”调用并附加换行符。如果没有另一个跟踪语句范围的对象,恕我直言,这是不可能的。

于 2012-10-20T11:28:46.073 回答