[英]How to overload std::cout << std::endl?
I was wondering if there was anyway I could overload std::cout << std::endl;
我想知道是否可以重载
std::cout << std::endl;
for the endl
to not only make a newline but also print a '-'
where the newline is supposed to be and then print another newline.对于
endl
不仅要创建换行符,还要在换行符应该在的位置打印一个'-'
,然后再打印另一个换行符。
Like if I did std::cout << std::endl << '-' << std::endl;
就像我做了
std::cout << std::endl << '-' << std::endl;
So I assume I must overload <<
but I'm not sure where to go from there for it to work with endl
.所以我假设我必须重载
<<
但我不确定从那里去哪里让它与endl
一起工作。
Inspired by the epic question about indenting std::ostream
instances , here is a codecvt class that will add the additional characters.受到关于缩进
std::ostream
实例的史诗问题的启发,这里是一个 codecvt 类,它将添加额外的字符。
The class was adapted from the popular answer by @MartinYork: I copy-pasted the class, adapted it to use a distinct character, and rewrote the for loop into a form I found more natural.该课程改编自@MartinYork 的流行答案:我复制粘贴了该课程,将其改编为使用不同的字符,并将 for 循环重写为我认为更自然的形式。
Here's a working example .这是一个工作示例。
#include <iostream>
#include <locale>
class augmented_newline_facet : public std::codecvt<char, char, std::mbstate_t>
{
const char addition = '-';
public:
explicit augmented_newline_facet(const char addition, size_t refs = 0) : std::codecvt<char,char,std::mbstate_t>(refs), addition{addition} {}
using result = std::codecvt_base::result;
using base = std::codecvt<char,char,std::mbstate_t>;
using intern_type = base::intern_type;
using extern_type = base::extern_type;
using state_type = base::state_type;
int& state(state_type& s) const {return *reinterpret_cast<int*>(&s);}
protected:
virtual result do_out(state_type& addition_needed,
const intern_type* rStart, const intern_type* rEnd, const intern_type*& rNewStart,
extern_type* wStart, extern_type* wEnd, extern_type*& wNewStart) const override
{
result res = std::codecvt_base::noconv;
while ((rStart < rEnd) && (wStart < wEnd))
{
// The last character seen was a newline.
// Thus we need to add the additional character and an extra newline.
if (state(addition_needed) == 1)
{
*wStart++ = addition;
*wStart++ = '\n';
state(addition_needed) = 0;
res = std::codecvt_base::ok;
continue;
}
else
{
// Copy the next character.
*wStart = *rStart;
}
// If the character copied was a '\n' mark that state
if (*rStart == '\n')
{
state(addition_needed) = 1;
}
++rStart;
++wStart;
}
if (rStart != rEnd)
{
res = std::codecvt_base::partial;
}
rNewStart = rStart;
wNewStart = wStart;
return res;
}
virtual bool do_always_noconv() const throw() override
{
return false;
}
};
int main(int argc, char* argv[]) {
std::ios::sync_with_stdio(false);
std::cout.imbue(std::locale(std::locale::classic(),
new augmented_newline_facet{'-'}));
for (int i = 0; i < 5; ++i)
{
std::cout << "Line " << i << std::endl;
}
}
How about defining your own function (or function template) that is akin to std::endl
:如何定义自己的类似于
std::endl
的函数(或函数模板):
std::ostream& enddash(std::ostream& os)
{
// Can use std::endl in place of '\n' if flushing desired.
os << "\n-\n";
return os;
}
Usage example:用法示例:
int main(int argc, char* argv[]) {
std::cout << "Hello, world." << enddash;
std::cout << "Hello, world, once again" << enddash;
}
Output:输出:
Hello, world.
-
Hello, world, once again
-
This is not as cool as @NicholasM's answer, but easier if the main really just contains std::cout << std::endl;
这不像@NicholasM 的回答那么酷,但如果 main 真的只包含
std::cout << std::endl;
更容易std::cout << std::endl;
: :
#include <stdio.h> // We don't want any iostream stuff, so we use the C header.
namespace std
{
struct dummy{};
dummy cout;
dummy endl;
dummy& operator<<(dummy &d, const dummy& other){
printf("\n-\n");
return d;
}
}
int main()
{
std::cout << std::endl;
}
I feel a bit dirty just writing this code...写这段代码我觉得有点脏......
Edit: To be exceedingly clear: I do not encourage anyone to use this code in any meaningful way (As @uneven_mark remarked, it contains UB).编辑:要非常清楚:我不鼓励任何人以任何有意义的方式使用此代码(正如@uneven_mark 所说,它包含 UB)。 It seems to me that the problem was posed to OP as some kind of gag or riddle, and hence I think something like this has the potential to be ok as an answer.
在我看来,这个问题是作为某种噱头或谜语向 OP 提出的,因此我认为这样的事情有可能作为答案。
You can do it with a macro definition for endl
.您可以使用
endl
的宏定义来实现。
I don't advise using it, but if you must...我不建议使用它,但如果你必须......
#include <iostream>
#include <string>
#define endl string("\n-\n") << std::flush
int main()
{
std::cout << std::endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.