如何重载std :: cout << std :: endl?

时间:2019-11-23 22:05:29

标签: c++ overloading std endl

我想知道是否无论如何我都可以使std::cout << std::endl;重载endl来不仅换行,而且还要打印一个'-',换行应该在该位置然后打印另一个换行符。

就像我做了std::cout << std::endl << '-' << std::endl;

因此,我假设我必须重载<<,但是我不确定从哪里可以使用endl

4 个答案:

答案 0 :(得分:2)

epic question about indenting std::ostream instances的启发,这是一个编解码器类,它将添加其他字符。

该类由@MartinYork的popular answer改编而成:我复制粘贴了该类,使它改编为使用不同的字符,然后将for循环重写为我发现更自然的形式。

这里是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;
    }
}

答案 1 :(得分:0)

如何定义类似于std::endl的自己的函数(或函数模板):

std::ostream& enddash(std::ostream& os)
{
    // Can use std::endl in place of '\n' if flushing desired.
    os << "\n-\n";  
    return os;
}

用法示例:

int main(int argc, char* argv[]) {
    std::cout << "Hello, world." << enddash;
    std::cout << "Hello, world, once again" << enddash;
}

输出:

Hello, world.
-
Hello, world, once again
-

答案 2 :(得分:0)

这不像@NicholasM的答案那么酷,但是如果主体实际上仅包含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;
}

我只是写这段代码感到有点脏...

编辑:非常清楚:我不鼓励任何人以任何有意义的方式使用此代码(如@uneven_mark所述,它包含UB)。在我看来,该问题是由OP引起的,是一种插科打or或谜语,因此,我认为类似这样的问题有可能作为答案。

答案 3 :(得分:0)

您可以使用endl的宏定义来做到这一点。

我不建议您使用它,但是如果您必须...

#include <iostream>
#include <string>

#define endl string("\n-\n") << std::flush

int main()
{
    std::cout << std::endl;
    return 0;
}