编写一个简单的函数,其工作方式与"std::cout"类似,但在末尾添加换行符



在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

通过创建一个在其析构函数中添加<< 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添加到std::shared_ptr<>拥有的内部对象,以便该示例不再依赖于 Copy Elision。

仅使用在堆栈上创建的非临时对象是不可能的,并且具有完整的功能范围。对象怎么会知道这是对<< 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";
}

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

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

事实上的代码

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

调用运算符函数

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

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

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

你的想法无法实现。实际上,cout << str1;等效于返回 cout 本身引用的cout.operator<<(str1)。因此,cout << a << b << c;可以解析为((cout << a) << b) << c;它不知道插入换行符的最后一次调用是什么时候。

相关内容

  • 没有找到相关文章

最新更新