2016-08-03 65 views
18

由於一些類型的可流:Stream對象直接進入的std :: string

struct X { 
    int i; 

    friend std::ostream& operator<<(std::ostream& os, X const& x) { 
     return os << "X(" << x.i << ')'; 
    } 
}; 

我想這追加到std::string。我可以爲實現這個:

void append(std::string& s, X const& x) { 
    std::ostringstream os; 
    os << x; 
    s.append(os.str()); 
} 

但是,這因爲我寫數據到一個流只是然後分配一個新的字符串只是其附加到一個不同的目的似乎跛。有更直接的路線嗎?

+0

我想看看http://www.boost.org/doc/libs/1_61_0/doc/html/interprocess/streams.html – bobah

+0

可能實現'std :: string X :: repr()'或類似的,並在'append'和'operator <<'中調用?不理想,但您避免使用中間'stringstream'。 – Praetorian

+0

簡單地說's.append(std :: string :: to_string(x));'?我錯過了一些重要的東西嗎 –

回答

13

這可以通過一種新型的streambuf來解決(參見Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference)。

這裏是它如何可以看看草圖:

#include <streambuf> 

class existing_string_buf : public std::streambuf 
{ 
public: 
    // Store a pointer to to_append. 
    explicit existing_string_buf(std::string &to_append); 

    virtual int_type overflow (int_type c) { 
     // Push here to the string to_append. 
    } 
}; 

一旦你在這裏充實的細節,你可以按如下方式使用它:

#include <iostream> 

std::string s; 
// Create a streambuf of the string s 
existing_string_buf b(s); 
// Create an ostream with the streambuf 
std::ostream o(&b); 

現在,你只寫o,結果應顯示爲附加到s

// This will append to s 
o << 22; 

編輯

由於@rustyx正確地指出,覆蓋xsputn需要提高性能。

完整的例子

下打印22

#include <streambuf> 
#include <string> 
#include <ostream> 
#include <iostream> 

class existing_string_buf : public std::streambuf 
{ 
public: 
    // Somehow store a pointer to to_append. 
    explicit existing_string_buf(std::string &to_append) : 
     m_to_append(&to_append){} 

    virtual int_type overflow (int_type c) { 
     if (c != EOF) { 
      m_to_append->push_back(c); 
     } 
     return c; 
    } 

    virtual std::streamsize xsputn (const char* s, std::streamsize n) { 
     m_to_append->insert(m_to_append->end(), s, s + n);                     
     return n; 
    } 

private: 
    std::string *m_to_append; 
}; 


int main() 
{ 
    std::string s; 
    existing_string_buf b(s); 
    std::ostream o(&b); 

    o << 22; 

    std::cout << s << std::endl; 
} 
+2

我也會重寫'xsputn()'以獲得良好的性能。 – rustyx

+0

@rustyx優秀的一點。添加。非常感謝 –

+4

有些時候,我覺得我知道C++。這不是其中之一。 – Barry

1

你可以寫一個的std :: string轉換操作符:

struct X { 
int i; 

friend std::ostream& operator<<(std::ostream& os, X const& x) { 
    os << "X(" << x.i << ')'; 
    return os; 
} 

operator std::string() { 
    return std::string("X(") + std::to_string(x.i) + ")"; 
} 

}; 

然後,你可以簡單地把它添加到std :: string:

X myX; 
myX.i = 2; 
std::string s("The value is "); 
s.append(myX); //myX is cast into the string "X(2)" 
+0

好的,但現在我有兩次相同的邏輯。 – Barry

+0

是的。將運算符<<方法的第一行更改爲「os << static_cast (x);」。 – HeywoodFloyd

-1

由於原始字符串對於現有分配可能只有足夠大的空間,所以您可以希望的最好方法是將所有要添加到流中的所有內容格式化,然後像在示例中那樣附加結果。

如果您打算經常執行這些附加操作,我會認爲std :: string是手頭問題的錯誤類型。我建議直接使用std :: ostringtream而不是std :: string,並且只在需要最終結果時才轉換爲字符串。

1

在這種特定的情況下,我只是遵循KISS原則:

struct X { 
    int i; 

    std::string toString() const { 
     return "X(" + std::to_string(i) + ")"; 
    } 
}; 

用法:

string += x.toString(); 
std::cout << x.toString(); 

operator<<(std::ostream&, …)是不是真的適合一般串轉換,因此,如果這就是你'之後再使用toString類型的方法/自由函數要好得多。如果你想std::cout << x,你可以簡單地實施operator<<只需撥打toString