這只是一個玩具。
它包含一個基於生成器的方式來吸取文件(我發現它很容易編寫),以及一個將Generators變成迭代器的半工作適配器。
在此上下文中的生成器是一個函子,它接受一個lambda,並將該lambda傳遞給該函數並返回true,或返回false。它使得一個非常短的循環:
while(gen([&](std::string line) {
// code using line goes here
})); // <- notice that this is an empty while loop that does stuff
但你不允許使用它。 (這個設計靈感來自於python生成器,對於許多類型的問題,包括從文件中讀取,我真的發現比C++迭代器更適合使用。
adpator使用此生成器並使其成爲迭代器,因此您可以將它傳遞給for_each
。
這個問題的關鍵在於你的問題本身就是一個愚蠢的問題,所以我並沒有做一些明顯的事情(goto,或者直接在istream迭代器上使用for_each
),我提議用一些愚蠢和不同的東西來搞亂。 :)
線發生器是好的,簡稱:
struct LineGenerator {
LineGenerator(std::ostream& os_):os(&os_) {}
std::ostream* os;
template<typename F>
bool operator()(F&& func) {
std::string s;
bool bRet = std::getline(*os, s);
if (!bRet) return false;
std::forward<F>(func)(s);
return true;
}
};
適配器,在另一方面,是相當混亂:(而不是測試)
template<typename Generator>
struct generator_iterator {
typedef generator_iterator<Generator> my_type;
typedef typename std::decay< decltype(std::declval<Generator>()()) >::type value_type;
Generator g;
bool bDone;
value_type val;
generator_iterator(Generator g_):g(g_), bDone(false) {
next();
}
generator_iterator(): bDone(true) {}
private:
void next() {
if (bDone) return;
bDone = g(val);
}
public:
generator_iterator& operator++() {
next();
return *this;
}
value_type operator*() {
return val;
}
const value_type operator*() const {
return val;
}
value_type* operator->() {
return &val;
}
value_type const* operator->() const {
return &val;
}
bool operator==(my_type const& o) {
if (bDone != o.bDone) return false;
if (!bDone && !o.bDone) return true;
return false;
}
};
template<typename Generator>
generator_iterator<Generator> make_gen_it(Generator&& g) {
return generator_iterator<Generator>(std::forward<Generator>(g));
}
template<typename Generator>
generator_iterator<Generator> make_end_gen_it() {
return generator_iterator<Generator>();
}
我希望這個遊樂!
爲什麼不能使用'for'或'while'循環? – 2013-04-05 16:56:58
這是很沒意思的,如果你逐行解析你的文字循環遍歷文件 – Paranaix 2013-04-05 16:58:24
像這樣愚蠢的要求,'goto'是最好的方法。 – nneonneo 2013-04-05 16:59:55