- Mastering the C++17 STL
- Arthur O'Dwyer
- 365字
- 2021-07-08 10:20:23
Write-only range algorithms
We began this chapter looking at algorithms such as std::find that march through a range reading its elements in order without modification. You might be surprised to learn that the inverse operation also makes sense: there is a family of standard algorithms that march through a range modifying each element without reading it!
std::fill(a,b,v) does what its name implies: fill each element of the given range [a,b) with a copy of the provided value v.
std::iota(a,b,v) is slightly more interesting: it fills the elements of the given range with copies of ++v. That is, std::iota(a,b,42) will set a[0] equal to 42, a[1] equal to 43, a[2] equal to 44, and so on all the way up to b. This algorithm's funny name comes from the APL programming language, where a function named ι (that's the Greek letter iota) performed this operation. Another funny thing about this algorithm is that, for whatever reason, its definition is found in the standard <numeric> header instead of in <algorithm>. It's just an oddball that way.
std::generate(a,b,g) is even more interesting: it fills the elements of the given range with the successive results of g(), whatever it is:
template<class FwdIt, class T>
void fill(FwdIt first, FwdIt last, T value) {
while (first != last) {
*first = value;
++first;
}
}
template<class FwdIt, class T>
void iota(FwdIt first, FwdIt last, T value) {
while (first != last) {
*first = value;
++value;
++first;
}
}
template<class FwdIt, class G>
void generate(FwdIt first, FwdIt last, G generator) {
while (first != last) {
*first = generator();
++first;
}
}
Here's an example of using each of these standard algorithms to fill a vector of strings with different contents. Test your understanding: do you understand why each call produces the output that it does? The example I picked for std::iota is particularly interesting (yet unlikely to be helpful in real-world code):
std::vector<std::string> v(4);
std::fill(v.begin(), v.end(), "hello");
assert(v[0] == "hello");
assert(v[1] == "hello");
assert(v[2] == "hello");
assert(v[3] == "hello");
std::iota(v.begin(), v.end(), "hello");
assert(v[0] == "hello");
assert(v[1] == "ello");
assert(v[2] == "llo");
assert(v[3] == "lo");
std::generate(v.begin(), v.end(), [i=0]() mutable {
return ++i % 2 ? "hello" : "world";
});
assert(v[0] == "hello");
assert(v[1] == "world");
assert(v[2] == "hello");
assert(v[3] == "world");
- Google Flutter Mobile Development Quick Start Guide
- Arduino開發實戰指南:LabVIEW卷
- BeagleBone Media Center
- 鋒利的SQL(第2版)
- Mastering Google App Engine
- BIM概論及Revit精講
- 劍指Java:核心原理與應用實踐
- Mastering Linux Security and Hardening
- Geospatial Development By Example with Python
- Clojure for Java Developers
- 數據分析與挖掘算法:Python實戰
- Learning C++ by Creating Games with UE4
- SEO教程:搜索引擎優化入門與進階(第3版)
- Modular Programming with JavaScript
- 計算機應用基礎(Windows 7+Office 2010)