我想我會做點事情有點不同。我可能已經做了一些比必要更復雜的工作 - 恐怕我可能會因爲嘗試使用新的C++ 11功能而有點疲憊。總之,在與代碼:
#include <streambuf>
#include <fstream>
#include <vector>
#include <iostream>
#include <initializer_list>
namespace multi {
class buf: public std::streambuf {
std::vector<std::streambuf *> buffers;
public:
typedef std::char_traits<char> traits_type;
typedef traits_type::int_type int_type;
buf(std::vector<std::ofstream> &buf) {
for (std::ofstream &os : buf)
buffers.push_back(os.rdbuf());
}
void attach(std::streambuf *b) { buffers.push_back(b); }
int_type overflow(int_type c) {
bool eof = false;
for (std::streambuf *buf : buffers)
eof |= (buf -> sputc(c) == traits_type::eof());
return eof ? traits_type::eof() : c;
}
};
class stream : public std::ostream {
std::vector<std::ofstream> streams;
buf outputs;
public:
stream(std::initializer_list<std::string> names)
: streams(names.begin(), names.end()),
outputs(streams),
std::ostream(&outputs)
{ }
void attach(std::ostream &b) {
outputs.attach(b.rdbuf());
}
};
}
int main() {
multi::stream icl({"c:\\out1.txt", "c:\\out2.txt"});
icl.attach(std::cout);
icl << "Blah blah blah" << std::endl;
}
正如你所看到的,這已經接受操縱(這應該與任何機械手的工作,而不僅僅是std::endl
)。如果你想要寫入多個文件(可以/可以作爲fstreams打開的東西),你可以在構造函數中指定儘可能多的這些名稱(當然,在你的系統限制的範圍內)。對於像std::cout
和std::cerr
這樣的文件,您不一定有文件名,您可以按照最初的設計使用attach
。
我想我應該補充一點,我並不完全滿意於此。這需要做一些相當嚴肅的重寫,但經過一番思考,我認爲「正確」的方式可能會讓multi::stream
的ctor成爲一個可變參數模板,所以您可以執行如下操作: multi::stream icl("c:\\out1.txt", std::cout);
,它會整理出如何根據其類型使用每個參數。我可能會很快更新這個答案以包含那個功能。
至於第二個問題,我寫了another answer,涵蓋了基本的想法,但可能有點過於詳細,所以你關心的部分可能會迷失在洗牌,可以這麼說 - - 處理不真正關心的行長度有相當多的邏輯(但是會像你想的那樣產生具有指定前綴的每個輸出行)。
問題1:Google運算符超載,您會看到很多示例。 – dutt 2013-04-21 19:40:23
我很清楚運算符重載是如何工作的,但是這裏似乎有點複雜,因爲有大量的數據類型可以輸入OutputMan,就像一個整數。當然有更好的方法。 – 2013-04-21 19:41:48
您可以爲可能需要特殊處理的類型使用具有特定模板重載/實例(不確定其稱謂)的模板。 – dutt 2013-04-21 19:44:02