簡體   English   中英

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

[英]How to overload std::cout << std::endl?

我想知道是否可以重載std::cout << std::endl; 對於endl不僅要創建換行符,還要在換行符應該在的位置打印一個'-' ,然后再打印另一個換行符。

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

所以我假設我必須重載<<但我不確定從那里去哪里讓它與endl一起工作。

受到關於縮進std::ostream實例史詩問題的啟發,這里是一個 codecvt 類,它將添加額外的字符。

該課程改編自@MartinYork 的流行答案:我復制粘貼了該課程,將其改編為使用不同的字符,並將 for 循環重寫為我認為更自然的形式。

這是一個工作示例

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

如何定義自己的類似於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
-

這不像@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;
}

寫這段代碼我覺得有點臟......

編輯:要非常清楚:我不鼓勵任何人以任何有意義的方式使用此代碼(正如@uneven_mark 所說,它包含 UB)。 在我看來,這個問題是作為某種噱頭或謎語向 OP 提出的,因此我認為這樣的事情有可能作為答案。

您可以使用endl的宏定義來實現。

我不建議使用它,但如果你必須......

#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM