簡體   English   中英

在重載的<<運算符中使用<<運算符

[英]Using a << operator inside an overloaded << operator

我正在編寫一個重載<<和>>運算符的類,類似於std :: istream和std :: ostream。 前幾個功能按預期工作。 但是,我想在我自己的類中使用其他std :: *流類來進行格式化,這會導致一個有趣的,我會說,'遞歸'編譯器問題:

class SmartStream
{
public:
    template <typename F> friend F &operator << (F &in, float f)
    {
        in.type ("f");
        in.m_buf.str ("");
        in.m_buf << f;          // This causes a 'recursive' compile call
        in.add (in.m_buf.str ());
        return in;
    }

protected:
    std::ostringstream m_buf;

    void type(const std::string &_type) {};
    void add(const std::string &) {};
};

實際錯誤很長,但它是這樣開始的:

rec_stream.cpp: In instantiation of 'F& operator<<(F&, float) [with F = std::basic_ostringstream<char>]':
rec_stream.cpp:14:18:   required from 'F& operator<<(F&, float) [with F = ExtraStream]'
rec_stream.cpp:60:11:   required from here
rec_stream.cpp:12:9: error: 'class std::basic_ostringstream<char>' has no member named 'type'
         in.type ("f");
         ^

顯然編譯器將相同的重載<<運算符應用於std :: ostringstream類型的m_buf變量,但當然沒有type()和add()函數。 看完這個問題的答案后有點意義,但沒有提供解決方案。

在你說之前沒有,在SmartStream中使用它:

class SmartStream 
{
   ....
    SmartStream &operator << (float f)
    {
        type("f");
        m_buf.str ("");
        m_buf << f;     // Ambiguous overload
        add( m_buf.str ());
        return *this;
    }
};

有兩個問題。 首先,如代碼中所述,觸發模糊的重載。 其次,請考慮以下事項:

class ExtraStream: public SmartStream
{
public:
    template <typename F> friend F &operator << (F &in, struct tm t)
    {
        in.type ("tm");
        in.m_buf.str ("");
        in.m_buf << t.tm_hour; // Ambiguous overload
        in.add (in.m_buf.str ());
        return in;
    }
};

實際上,我正在擴展SmartStream以使用該類中布置的機制來處理自定義類型。 使用非朋友操作員將不允許我這樣做:

ExtraStream es;

struct tm t1, t2;
float f1, f2;

es << f1 << t1 << f2 << t2; // works

因為在<< (float)返回類型是SmartStream,它不知道如何處理struct tm

我的問題:

有沒有辦法說服編譯器(gcc 4.8.2)對std :: ostringstream使用'base'<<運算符而不是重載的運算符? 我嘗試了各種演員,::解析運算符,用in.m_buf << f;移動代碼in.m_buf << f; 到SmartStream中的非模板化函數但沒有任何幫助。

另外,為什么它只在模板運算符<< function?中使用它? 在該函數之外的任何使用<< on std :: ostringstream都可以正常工作。

我在gcc buglist上發布了這個,因為我覺得這是一個bug或至少在C ++參考中有歧義。 Jonathan Wakely提出了一個非常簡單的解決方案:

template <typename F> friend F &operator << (F &in, float f)
{
    in.type ("f");
    in.m_buf.str ("");
    using std::operator <<;  // indicate proper operator in the next line
    in.m_buf << f;          
    in.add (in.m_buf.str ());
    return in;
}

所以它確實需要一個using條款,只是一個我不希望的。

因此,我認為最簡單的方法是使用類似std::enable_if限制友元函數,以便它們僅在具有正確父類的流上有效。

#include <sstream>
#include <type_traits>

class SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<SmartStream, F>::value, F&>::type
        operator << (F &in, float f) {
            in.type("f");
            in.m_buf.str("");
            in.m_buf << f;
            in.add (in.m_buf.str ());
            return in;
        }

    protected:
        std::ostringstream m_buf;

        void type(const std::string &_type) {};
        void add(const std::string &) {};
};

class ExtraStream: public SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<ExtraStream, F>::value, F&>::type
        operator << (F &in, struct tm t) {
            in.type ("tm");
            in.m_buf.str ("");
            in.m_buf << t.tm_hour;
            in.add (in.m_buf.str ());
            return in;
        }
};

int main() {
    SmartStream ss;
    ExtraStream es;
    struct tm t;

    ss << 3.14f;
    es << 3.14f << t << 3.14;
    // ss << t; // Fails as expected.
}

暫無
暫無

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

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