簡體   English   中英

在C ++嘗試在每個運算符重載級聯后寫一個換行符

[英]In C++ trying to write a newline after each operator overload cascade

這有點難以破解。 我正在編寫一個日志函數,試圖與std :: cout具有相似的外觀

所以基本上我們的目標是讓以下代碼按照評論進行操作

   log << "text"; // This would output "text\n";
   log << "some " << "text"; //This would output "some text\n"
   log << "some number "<< 5; //This would output "some number 5\n"

我嘗試過使用可變參數模板,但沒有達到目的。 這是迄今為止最成功的嘗試:

#include <iostream>

// stream_newliner works by just taking the address of an ostream you
// give it, and forwarding all writes (via operator<<) to that ostream.
// Then, when it finally destructs, it writes the newline.
template <typename CharT, typename Traits>
class stream_newliner
{
public:
// The constructor just takes the address of the stream you give it.
explicit stream_newliner(std::basic_ostream<CharT, Traits>& s) :
    p_s_{&s}
{}

// Boilerplate move construction. Nothing special here.
stream_newliner(stream_newliner&& s) : p_s_{nullptr}
{
    *this = std::move(s);
}

// On destruction, write the newline. (Note we check the pointer for
// null for technical reasons.)
~stream_newliner()
{
    if (p_s_)
    {
        // If you have std::unhandled_exceptions(), you can check to
        // see if a new exception is in flight, and only do the
        // newline if there's not.

        // Note that I'm writing an X and not a newline so you can
        // see it easier.
        (*p_s_) << 'X';
    }
}

// This is where the magic happens. Any time you do "x << y" where
// x is this type, it just passes it on to the underlying stream.
// When you do "x << y1 << y2", it all works magically because it
// translates to "operator<<(operator<<(x, y1), y2)"... and this
// function just passes each call to the underlying stream.
template <typename T>
auto operator<<(T&& t) -> stream_newliner<CharT, Traits>&
{
    (*p_s_) << std::forward<T>(t);
    return *this;
}

// Boilerplate move assignment. Nothing special here.
auto operator=(stream_newliner&& s) -> stream_newliner&
{
    std::swap(p_s_, s.p_s_);
    return *this;
}

// Technically don't need these, but it doesn't hurt to be explicit.
stream_newliner(stream_newliner const&) = delete;
auto operator=(stream_newliner const&) = delete;

   private:
// You could use a reference to the stream rather than a pointer,
// but references are harder to work with as class members.
std::basic_ostream<CharT, Traits>* p_s_ = nullptr;
   };

   // Helper function to make it easier to create.
   template <typename CharT, typename Traits>
   auto line(std::basic_ostream<CharT, Traits>& s)
   {
return stream_newliner<CharT, Traits>{s};
   }

   auto main() -> int
   {
line(std::cout) << "foo";
std::cout << '\n';

line(std::cout) << 1 << ' ' << 2 << ' ' << 3;
std::cout << '\n';
   }

我認為這不是太棘手。 讓我們來看看:

struct eol_log
{
    eol_log(std::ostream& os) : os_(os) {}
    ~eol_log() { os_ << '\n'; }

    template <typename T>
    std::ostream& operator<<(const T& t) && { return os_ << t; }

    std::ostream& os_;
};

用法:

eol_log(std::cout) << "Foo" << "Bar" << 10;
eol_log(std::cout) << 10;

臨時對象充當一種“全面表達守衛”。

如果你想要一個充當你的日志接收器的永久對象,那么你可以將上面的內容包裝在一個類中,但現在你需要移動成為鏈中最后一個元素的狀態:

class EolLogger
{
    class RvalLog
    {
        friend class EolLogger;

        RvalLog(std::ostream* os) : os_(os) {}
        RvalLog(RvalLog&& rhs) : os_(rhs.os_) { rhs.os_ = nullptr; }
        std::ostream* os_;

    public:
        template <typename T>
        RvalLog operator<<(const T& t) && { *os_ << t; return std::move(*this); }

        ~RvalLog() { if (os_) *os_ << '\n'; }
    };

    std::ostream& os_;

public:
    EolLogger(std::ostream& os) : os_(os) {}

    template <typename T>
    RvalLog operator<<(const T& t) { return RvalLog(&os_) << t; }
};

用法:

EolLogger elog(std::cout);

elog << "Foo";
elog << 1 << 2 << 3;

有人發布了這個,並且它完成了這項工作。

#include <iostream>
using namespace std;

struct Liner {
    bool Owned = true;
    Liner() = default;
    Liner(Liner &&O) { O.Owned = false; }
    ~Liner() { if (Owned) std::cout << '\n'; }
};

template <typename T>
const Liner &operator<<(const Liner &L, T &&E) {
    std::cout << std::forward<T>(E);
    return L;
}

struct SubLiner {
    operator Liner() const { return {}; }
};

const static SubLiner line;

int main() {
    line << "hello " << "world!";
    line << 1 << 2;
    line << 3;
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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