使用 Range Adaptors 的函数式 STL






3.75/5 (20投票s)
Aug 27, 2006
23分钟阅读

38891

255
Introduction to Functional STL Library using Boost.Range Adaptors.
1 引言
Oven provides an experimental Range Adaptor implementation of Range Library Proposal
typedef any_range<int, boost::single_pass_traversal_tag> range; range sieve(range rng) { return rng|dropped(1)|filtered(regular(lambda::_1 % front(rng) != 0)); } range primes = iteration(range(counting_from(2)), &::sieve)|transformed(front); int main() { std::cout << (primes|taken(200)); }
All the types and functions are defined innamespace pstade::ovenat<pstade/oven.hpp>unless otherwise specified.
2 Requirements
- Boost C++ Libraries Version 1.33.1 or later (no compilation required)
- P-Stade C++ Libraries Version 1.02.0 or later (no compilation required, give a higher priority than Boost headers)
3 Tested Under
- Microsoft Visual C++ 2005 Express Edition SP1
- Microsoft Visual C++ .NET Version 7.1 SP1
- GCC 3.4.4
4 Specification
This document is based on the following specifications.
- rng: any range
- fwdRng: any Forward Range
- biRng: any Bidirectional Range
- rndRng: any Random Access Range
- pred: any Predicate
- rfun: any Function Object [1] which can be used withboost::result_of.
- Ifxxx(a1,..,aN)is a valid expression andxxxis not a type name,xxxis a Function Object whose type name isop_xxxto supportboost::result_ofand Boost.Lambda.
std::string src("hello, specification"); boost::result_of<op_make_filtered(std::string&, bool(*)(char))>::type result = make_filtered(src, &is_upper); BOOST_CHECK( equals(result, src|filtered(&is_upper)) );
All the ranges Oven defines areInputStreamable和OutputStreamableif<pstade/oven/io.hpp>is included.
[1] | The function type is not supported asrfun. Instead, add&to make a function pointer. |
5 Range Algorithms
Oven provides some range-based algorithms.<pstade/oven/functions.hpp>includes all the following functions unless otherwise specified.
5.1 STL Algorithms
Oven has all the range-based STL algorithms, which are ported from Boost.RangeEx with some compiler workarounds
std::string str; // iterator-based str = "gfedcba"; std::sort(str.begin(), str.end()); BOOST_CHECK( str == "abcdefg" ); // Oven range-based str = "gfedcba"; oven::sort(str); BOOST_CHECK( str == "abcdefg" );
- 标题<pstade/oven/algorithm.hpp>和<pstade/oven/numeric.hpp>
- Valid expressionalgo(rng,a0,a1,..,aN), wherealgois a Function Object.
- Preconditionstd::algo(boost::begin(rng),boost::end(rng),a0,a1,..,aN)is a valid expression, wherealgois one of the STL algorithms.
- Returnsstd::algo(boost::begin(rng),boost::end(rng),a0,a1,..,aN)
5.2 adapted_to/to_base
adapted_togets thebase_typeiterator of adapted iterators
std::string src("cjaigvwzenqhe");
std::string::iterator it = oven::adapted_to<std::string::iterator>(
oven::max_element(
src
| filtered(regular(lambda::_1 != 'z'))
| filtered(regular(lambda::_1 != 'w'))
)
);
BOOST_CHECK( *it == 'v' );
- 标题<pstade/oven/adapted_to_base.hpp>
- Valid expressionBaseIter base = oven::adapted_to<BaseIter>(it);或BaseIter base = it|to_base; [2]
- Precondition: The type ofbaseisBaseIter, anditis an adapted iterator.
[2] | to_baseadds the automatic type deduction toadapted_to. |
5.3 begin/end
begin/endis a pipable version ofboost::begin/end:
std::string src("abcDefg"); oven::copy(src|reversed|transformed(to_upper), src|reversed|begin); BOOST_CHECK( oven::equals(src, std::string("ABCDEFG")) );
- 标题<pstade/oven/begin_end.hpp>
- Valid expressionrng|begin和rng|end
- Preconditionboost::begin(rng)和boost::end(rng)is a valid expression.
- Returnsboost::begin(rng)和boost::end(rng)respectively.
5.4 compile
Pending...
compileintroduces the syntax sugar forjointedetc
std::string rng1("12"); std::list<char> rng2 = std::string("34")|copied; std::vector<char> rng3 = std::string("56")|copied; BOOST_CHECK( equals( compile( +(rng1 >> (rng2|as_term) >> rng3) ) | taken(17), std::string("12345612345612345") ) );
- 标题<pstade/oven/compile.hpp>
- Valid expressioncompile(rngExpr)
5.5 copied
copiedadds the automatic type deduction to copy_range which calls the range constructor of the STL Sequences
std::vector<int> vec = oven::counting(3, 9)|copied; vec.push_back(9); BOOST_CHECK( oven::equals(vec, oven::counting(3, 10)) );
- 标题<pstade/oven/copy_range.hpp>
- Valid expressionSeq seq = rng|copied; [3]
- PreconditionSeq seq = boost::copy_range<Seq>(rng);is a valid expression.
- EffectSeq seq = boost::copy_range<Seq>(rng);
[3] | Seq seq(rng|copied);is not a valid expression. |
5.6 distance
The upcoming Boost.Range will replaceboost::sizebyboost::distance. oven::distancethat is the same asboost::distancemakes your code portable
std::string str("012345"); BOOST_CHECK( oven::distance(str) == 6 );
- 标题<pstade/oven/distance.hpp>
- Valid expressiondistance(rng)
- Preconditionstd::distance(boost::begin(rng),boost::end(rng))is a valid expression.
- Returnsstd::distance(boost::begin(rng),boost::end(rng))
5.7 equals
equalsis the range-basedstd::equalthat takes two ranges as the arguments
std::string str("hello, equals"); std::vector<char> vec = str|copied; BOOST_CHECK( oven::equals(str, vec) );
- 标题<pstade/oven/equals.hpp>
- Valid expressionequals(rng1,rng2)
- Preconditionequal(rng1,boost::begin(rng2))is a valid expression.
- Returnstrueif and only if theoven::equal(rng1,boost::begin(rng2))和boost::size(rng1) == boost::size(rng2)returnstrue. [4]
[4] | The size of two ranges too is checked. |
5.8 front/back
- 标题<pstade/oven/front_back.hpp>
- Valid expressionfront(rng)和back(biRng).
- Preconditionboost::range_valueofrngisCopyConstructible.
- ReturnsV(*boost::begin(rng))和V(*--boost::end(biRng))respectively, whereVisboost::range_valueofrng. [5]
[5] | They don't return references because of 24.1/9. |
6 Utilities
Some helper function objects are given to fill the gap between Oven and other libraries.
6.1 innumerable
As discribed below, the function object generation needs is slightly different from the Generator concept defined by the Standard.innumerableturns the Generator function object into the Standard conforming one, which creates an infinite range, working with generation.
- 标题<pstade/oven/generation.hpp>
- Valid expressioninnumerable(rfun)
- Returns: A generation conforming function object.
6.2 regular
Boost.Lambda functors are neitherDefaultConstructiblenorCopyAssignable. An iterator holding such a functor cannot conform to evenInputIterator. So that,regularconverts it to comfortable one for iterators. [6]
- 标题<pstade/oven/regular.hpp>
- Valid expressionregular(lambdaFunctor)
- Returns: Arfunwhich isDefaultConstructible和CopyAssignable.
In principle, callregularbefore a lambda functor is passed to Range Adaptors.
[6] | regularincidentally converts the functor into the one which can take non-const rvalues. |
6.3 shared_regular
shared_regularconverts a noncopyable function object type to copyable one.
- 标题<pstade/oven/regular.hpp>
- Valid expressionshared_regular(p).
- Preconditionboost::shared_ptris constructible fromp.
- Returns: Arfunwhich isDefaultConstructible和CopyAssignable.
7 Ranges
Oven provides some predefined range types.<pstade/oven/ranges.hpp>includes every range header unless otherwise specified.
7.1 any_range
Oven supportsboost::result_of, but it is sometimes cumbersome to get the type of the adapted range.any_rangebehaves as the type erasure of ranges
any_range<int, boost::single_pass_traversal_tag> factorials = counting_from(1) | scanned(1, regular(lambda::_1 * lambda::_2));
- 标题<pstade/oven/any_range.hpp>
- Valid expressionany_range<R,T> any_;, any_range<R,T> any_(rng);和any_range<R,T> any_ = rng;, where the iterators ofany_areInteroperatableif and only ifrngs are the same type.
- Preconditionboost::range_referenceofrngis convertible toRwithout creating rvalue.Tis aTraversalTag.
- Returns: A range whose iterators behave as if they were the original iterators wrapped in any_iterator
7.2 array_range
array_rangeis a non-Copyable Random Access Range which delivers a range presentation of dynamically allocated arrays
std::string str("hello, array_range!"); boost::array<char, 19> sarr; oven::copy(str, sarr|begin); oven::array_range<char> darr(19); oven::copy(str, darr|begin); BOOST_CHECK( oven::equals(sarr, darr) );
- 标题<pstade/oven/array_range.hpp>
- Valid expressionarray_range<T> rng(sz);
- Preconditionnew T[sz];is a valid expression.
7.3 directory_range
directory_rangeis a Single Pass Range which accesses the contents of a directory
BOOST_FOREACH (
filesystem::path const& pt,
directory_range(filesystem::current_path()))
{
std::cout << pt.leaf() << std::endl;
}
- 标题<pstade/oven/directory_range.hpp>; not included by<pstade/oven/ranges.hpp>
- Valid expressiondirectory_range rng(p);和wdirectory_range wrng(wp);
- Precondition: The type ofpisboost::filesystem::pathand the type ofwpisboost::filesystem::wpath.
- Returns: A range whose iterators behave as if they were the original iterators wrapped in directory_iterator
7.4 empty_range
empty_rangeis a Random Access Range which is always empty
BOOST_CHECK( boost::empty(empty_range<int>()) );
- 标题<pstade/oven/empty_range.hpp>
- Valid expressionempty_range<T> rng;
7.5 file_range
file_rangeis a constant Random Access Range for files
std::vector<char> vec; oven::copy(file_range<char>("data.txt"), std::back_inserter(vec));
- 标题<pstade/oven/file_range.hpp>
- Valid expressionfile_range<C> rng;和rng.is_open();
- Preconditionboost::spirit::file_iterator<C>is a valid expression.
- Returns: A range whose iterators behave as if they were the original iterators wrapped in file_iterator
The memberis_open()returnstrueif and only if the file opening is succeeded. Ifis_open()is nottrue, the range is empty.
8 Range Makers
Oven provides some predefined functions which produce a range. All the range returned from the following makers areCopyConstructible和Inheritable. <pstade/oven/functions.hpp>includes every maker header unless otherwise specified.
8.1 as_array
The current Boost.Range regards char array as literal, whichas_arrayworks around.
- 标题<pstade/oven/as_array.hpp>
- Valid expressionas_array(arr)和arr|as_array
- Effect: same as TR2 as_array
8.2 as_c_str
as_c_strmakes a Random Access Range from null-terminated c-style string
{ wchar_t const *psz = L"hello range"; BOOST_CHECK( oven::equals(psz|as_c_str, std::wstring(L"hello range")) ); } { std::string src("hello range"); BOOST_CHECK( oven::equals(src.c_str()|as_c_str, src) ); }
- 标题<pstade/oven/as_c_str.hpp>
- Valid expression2as_c_str(x)和x|as_c_str.
- Returns: Ifxis convertible to a char pointer,[x,x+strlen(psz)); otherwise,[boost::begin(x),oven::find(x,0)).
8.3 as_literal
as_literalmakes a Random Access Range from character array.as_literaldoesn't support any pointer type but array type. So it is safe and fast. Compare it withas_c_str:
{ BOOST_CHECK( oven::equals("hello range"|as_literal, std::string("hello range")) ); } { BOOST_CHECK( oven::equals( "hello\0range"|as_c_str, std::string("hello") ) ); BOOST_CHECK( oven::equals( "hello\0range"|as_literal, std::string("hello")|jointed('\0'|as_single)|jointed(std::string("range")) ) ); }
- 标题<pstade/oven/as_literal.hpp>
- Valid expression1as_literal(x)和x|as_literal
- Returns:Ifxis an array,[&x[0],&x[0]+sz-1)其中szis the size ofarr; otherwise,xas is. [7]
[7] | as_literaldoesn't usestrlen. TR2 as_literal does. |
8.4 as_single
as_singlemakes a Random Access Range which delivers a range presentation of one object
BOOST_CHECK( oven::equals('a'|as_single, std::string("a")) );
- 标题<pstade/oven/as_single.hpp>
- Valid expressionas_single(v)和v|as_single
- Returns: A range which behaves as if it were[&v,&v+1).
8.5 as_shared_single
- 标题<pstade/oven/as_single.hpp>
- Valid expressionas_shared_single(p)和p|as_shared_single
- Preconditionboost::shared_ptris constructible fromp.
- Returns: A range which behaves as if it were[&*p,&*p+1).
8.6 counting
countingintroduces the replacement offorloop
int ans[] = { 2, 3, 4, 5, 6 }; BOOST_CHECK( oven::equal(counting(2, 7), ans) ); std::vector<int> vec; BOOST_FOREACH (int i, counting(0, 5)) { vec.push_back(i); }
- 标题<pstade/oven/counting.hpp>
- Valid expressioncounting(n, m), wheren和misIncrementable.
- Returns: A range whose iterators behave as if they were the original iterators wrapped in counting_iterator
8.7 counting_from
- 标题<pstade/oven/counting.hpp>
- Valid expressioncounting_from(n), wherenisIncrementable.
- Returns: A range which behaves as ifcounting(n,std::numeric_limits<N>::max()), whereNis the type ofn.
8.8 generation
generationreturns a range whose iterators were originally written as generator_iterator
struct rand_generator { typedef boost::optional<long> result_type; result_type operator()() { long result = std::rand(); if (result % 3 == 0) return result_type(); // range is end. return result; } }; void test() { rand_generator X; BOOST_FOREACH (long x, oven::generation(X)) { std::cout << x << std::endl; } }
- 标题<pstade/oven/generation.hpp>
- Valid expressiongeneration(rfun)
- Preconditionrfuncall returns initializedboost::optionalif range is not end; Otherwise, returns uninitialized one.
- Returns: A Single Pass Range whose values are the results of invokingrfun.
If you have a Standard conforming Generator, you can convert it togenerationconforming one by using innumerable.
8.9 indexing
Pending...
8.10 iteration
iterationmakes an infinite range where the first item is calculated by applying the function on the first argument, the second item by applying the function on the previous result and so on
int answer[] = { 1,2,4,8,16 }; BOOST_CHECK( oven::equals(answer, oven::iteration(1, regular(lambda::_1 * 2))|oven::taken(5) ) );
- 标题<pstade/oven/iteration.hpp>
- Valid expressioniteration(x,fun)
- Returns: An infinite [8] Single Pass Range of repeated applications offuntox.
[8] | Strictly speaking, the Single Pass Range concept doesn't allow an infinite range. So assume here the end iterator is reachable from the begin iterator in the googolplex number of increments. |
8.11 recursion
recursion, collaborating with any_range, creates a recursive [9] range
typedef any_range<int const&, boost::forward_traversal_tag> range_t; range_t fibs; memo_table tb; int const start[] = { 1, 1 }; fibs = start | transformed(pstade::as_value) | jointed( boost::make_tuple(recursion(fibs), recursion(fibs)|dropped(1)) | zipped_with(regular(lambda::_1 + lambda::_2)) ) | memoized(tb) ; std::cout << (fibs|taken(howMany));
- 标题<pstade/oven/recursion.hpp>
- Valid expressionrecursion(fwdRng), wherefwdRngis anany_rangeobject.
- Returns: An infinite range up to Bidirectional Range.
[9] | In a recursive range,memoizedmust take a namedmemo_tableobject. A recursive range tends to be inefficient without memoization. |
8.12 repeated
repeatedmakes a Random Access Range where all values are the first argument
BOOST_CHECK( oven::equals( 'A'|repeated(6), std::string("AAAAAA") ) );
- 标题<pstade/oven/repeated.hpp>
- Valid expressionv|repeated(c)和make_repeated(v,c)
- Returns: A range which behaves as if it wereas_single(v)|cycled(c).
8.13 stream_input
stream_inputmakes a Single Pass Range fromstd::coutetc
std::string src("hello,stream_input!"); std::stringstream ss; ss << src; std::string result; oven::copy(oven::stream_input<char>(ss), std::back_inserter(result)); BOOST_CHECK( oven::equals(result, src) );
- Valid expressionoven::stream_input<V>(stm)
- Returns: A range whose iterators behave as if they were the original iterators wrapped in istream_iterator
8.14 streambuf_input
- 标题<pstade/oven/stream_input.hpp>
- Valid expressionoven::streambuf_input(stm)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inistreambuf_iterator
9 Range Adaptors
A Range Adaptor delivers an altered presentation of one or more underlying ranges. Range Adaptors are lazy, meaning that their elements are only computed on demand. The underlying ranges are not modified. Additional information is available at Range Library Proposal.<pstade/oven/adaptors.hpp>includes all the following Range Adaptors unless otherwise specified.
Note that all the range returned from the following adaptors areCopyConstructible和Inheritable. Also, ifa0|xxx(a1,..,aN)is a valid expression, thenmake_xxx(a0,..,aN)too is a valid expression which has the same effect.
9.1 adjacent_filtered
- 标题<pstade/oven/adjacent_filtered.hpp>
- See: Range Library Proposal.
9.2 adjacent_transformed
- 标题<pstade/oven/adjacent_transformed.hpp>
- Valid expressionfwdRng|adjacent_transformed(rfun)
- Preconditionboost::empty(fwdRng) == false
- Returns: A range where adjacent pairs offwdRngare transformed by usingrfun.
9.3 advanced
- 标题<pstade/oven/advanced.hpp>
- Valid expressionfwdRng|advanced(d1,d2)
- PreconditionfwdRngmust be a Bidirectional Range if eitherd1或d2is negative.
- Returns[boost::next(boost::begin(fwdRng),d1),boost::next(boost::end(fwdRng),d2)).
9.4 always
alwaysreturns a range which does not change as the base range vary
BOOST_CHECK( oven::equals( std::string("labor") | jointed(std::string("will be")) | always("lost"), std::string("lost") ) );
- 标题<pstade/oven/always.hpp>
- Valid expressionunusedRng|always(rng)
- Returns[boost::begin(rng),boost::end(rng)).
9.5 appended
appendedreturns a range which is appended with its argument
std::string const str("hello, appen"); BOOST_CHECK( oven::equals( str|appended('d')|appended('e')|appended('d')|appended('!'), std::string("hello, appended!") ) );
- 标题<pstade/oven/appended.hpp>
- Valid expressionrng|appended(v)
- Returns: A range which behaves as if it wererng|jointed(as_single(v)).
9.6 applied
applied, taking a Function Object which represents an algorithm, creates the range adaptor
namespace lambda = boost::lambda; std::string src("abcdefghijk"); std::string s1("efg"); BOOST_CHECK(( oven::equals( std::string("efghijk"), src|applied(lambda::bind(oven::search, lambda::_1, s1), oven::end) ) ));
- 标题<pstade/oven/applied.hpp>
- Valid expression1rng|applied(f1,f2), wheref1(rng)和f2(rng)must return iterators that are convertible torng's.
- Valid expression2rng|applied(f), wheref(rng)must return a range whose iterators are convertible torng's.
- Returns[f1(rng),f2(rng)), or[boost::begin(r),boost::end(r))其中r = f(rng), respectively.
9.7 broken_into
broken_intois the adaptor version ofboost::tokenizer:
int const offsets[] = { 2,2,4 }; std::string src("12252001"); std::vector<std::string> ans; { ans.push_back("12"); ans.push_back("25"); ans.push_back("2001"); } BOOST_CHECK( oven::equals( ans, src|broken_into<std::string>(boost::offset_separator(offsets, offsets+3)) ) );
- 标题<pstade/oven/broken_into.hpp>
- Valid expressionrng|broken_into<t>(f), wherefis aTokenizerFunction.
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::token_iterator.
9.8 checked
checkedadds the bounds checking ability to the base range
std::string in("012345"); std::string out("01234"); try { oven::copy(in, boost::begin(out|checked)); } catch (check_error const& ) { return; } BOOST_CHECK(false);
- 标题<pstade/oven/checked.hpp>
- Valid expressionrng|checked
- Effect: Throwscheck_errorderived fromstd::range_errorif iterators go out ofrng.
- Returns[boost::begin(rng),boost::end(rng))
9.9 cleared
clearedreturns a range which is always empty
BOOST_CHECK( boost::empty( std::string("labor") | jointed(std::string("lost")) | cleared ) );
- 标题<pstade/oven/cleared.hpp>
- Valid expressionrng|cleared
- Returns[boost::end(rng),boost::end(rng)).
9.10 concatenated
concatenatedaccepts a range whosevalue_typeis a range and concatenates them
std::string input("This is his face"); boost::regex re("\\w+"); BOOST_CHECK( oven::equals( input|tokenized(re)|concatenated, std::string("Thisishisface") ) );
- 标题<pstade/oven/concatenated.hpp>
- Valid expressionrngs|concatenated
- SpecificationSegmentIteratoris an iterator ofrngs, andLocalIteratoris an iterator of the range which the dereference ofSegmentIteratorreturns.
- Precondition: TheLocalIteratormust be valid after copying ofSegmentIterator.
9.11 constants
- 标题<pstade/oven/constants.hpp>
- Valid expressionrng|constants
- Returns[boost::end(rng),boost::end(rng))whose iterators are constant.
9.12 const_lvalues
const_lvaluesturns the associatedreferencetype of the base range into reference type, which makes iterators of Forward Range conform toForwardIterator. Thus, STL that doesn't know traversal concepts can choose effective algorithms.
- 标题<pstade/oven/const_lvalues.hpp>
- Valid expressionrng|const_lvalues
- Preconditionvalue_typeofrngisCopyConstructible, Assignable和DefaultConstructible.
- Returns[boost::begin(rng),boost::end(rng))whose iterators are constant.
9.13 copied_out
copied_outmakes a side-effect that copies the base range to its argument
std::string src("axaxaxbxbxbx"); std::string snapshot; std::string answer("bbb"); BOOST_CHECK( oven::equals( src | filtered(regular(lambda::_1 != 'x')) | copied_out(std::back_inserter(snapshot)) | filtered(regular(lambda::_1 != 'a')), answer ) ); BOOST_CHECK( snapshot == "aaabbb" );
- 标题<pstade/oven/copied_out.hpp>
- Valid expressionrng|copied_out(it)
- Preconditionoven::copy(rng,it)is a valid expression.
- Effectoven::copy(rng,it)
- Returnsrng.
9.14 cycled
cycledcreates a circular range from the base range
BOOST_CHECK( oven::equals( std::string("xyz")|cycled(3), std::string("xyzxyzxyz") ) );
- 标题<pstade/oven/cycled.hpp>
- Valid expressionrng|cycled(n)
- Returns: A constant range that repeats[boost::begin(rng),boost::end(rng)) ntimes.
9.15 delimited
delimitedadds a delimiter to the base range
BOOST_CHECK( equals( std::string("abcde")|transformed(as_single)| delimited("--"|as_literal)|dropped(2), std::string("a--b--c--d--e") ) );
- 标题<pstade/oven/delimited.hpp>
- Valid expressionrngs|delimited(delim), wheredelimis a Range to specify the delimiter.
- Returns: A range which behaves as if it wererngs|transformed(with)|concatenated, where用is a Function Object which callsmake_jointedto jointdelim. [10]
[10] | delimitedprepends the delimiter.droppedis useful to remove it. |
9.16 directed
directedreturns a range whose values are iterators of the base range
std::string const str("gefadcb"); std::string const answer("abcdefg"); std::vector<std::string::const_iterator> iters; oven::copy(str|directed, std::back_inserter(iters)); oven::sort( iters, boost::make_indirect_fun(::less_than()) ); BOOST_CHECK( oven::equals(iters|indirected, answer) );
- 标题<pstade/oven/directed.hpp>
- Valid expressionrng|directed
- Returns: A range which behaves as if it werecounting(boost::begin(rng),boost::end(rng)).
9.17 dropped
droppedreturns the suffix of the base range after the firstnelements
BOOST_CHECK( oven::equals( std::string("hello, dropped!")|dropped(7), std::string("dropped!") ) );
- 标题<pstade/oven/dropped.hpp>
- Valid expressionrng|dropped(n)
- Precondition0 <= n
- Returns[boost::next(boost::begin(rng),std::min(n,distance(rng))),boost::end(rng))
9.18 dropped_while
dropped_whilereturns the remaining suffix of the base range of elements that satisfy Predicate
std::string src("11111234516313!"); BOOST_CHECK( oven::equals( src|dropped_while(lambda::_1 == '1'), std::string("234516313!") ) );
- 标题<pstade/oven/dropped_while.hpp>
- Valid expressionrng|dropped_while(pred)
- Returns[oven::find_if(rng, not_(pred)),boost::end(rng))
9.19 filtered
filteredreturns a range which is filtered by using a Predicate [11]
int src[] = { 2,5,2,6,1,3,2 }; int answer[] = { 0,5,0,6,1,3,0 }; BOOST_FOREACH (int& i, src|filtered(regular(lambda::_1 == 2))) { i = 0; } BOOST_CHECK( oven::equals(answer, src) );
- 标题<pstade/oven/filtered.hpp>
- See: Range Library Proposal.
[11] | A non-assignable lambda functor makesfilterednon-conforming, so it needs regular to be applied before it is passed. |
9.20 firsts
- 标题<pstade/oven/firsts.hpp>
- Valid expressionrng|firsts
- Returns: A range which behaves as if it wererng|map_keys.
9.21 got_at
Pending...
- 标题<pstade/oven/got_at.hpp>
- Valid expressionrng|got_at<N>()或rng|got_at_c<N>(), wherevalue_typeofrngis a Fusion Sequence.
9.22 identities
identitiesreturns a range which is identical to the base range
BOOST_CHECK( oven::equals( std::string("hello, identities!")|identities, std::string("hello, identities!") ) );
- 标题<pstade/oven/identities.hpp>
- Valid expressionrng|identities和rng|identities(trv), wheretrvis a traversal tag object.
- Preconditionrng's traversal tag is convertible totrv.
- Returns[boost::begin(rng),boost::end(rng)).
9.23 indirected
indirectedadapts the base range by applying an extra dereference inside ofoperator*():
int src[] = { 1,2,0,4,5 }; int answer[] = { 1,2,3,4,5 }; int *ptrs[] = {&src[0],&src[1],&src[2],&src[3],&src[4]}; BOOST_FOREACH (int& i, ptrs|indirected) { if (i == 0) i = 3; } BOOST_CHECK( oven::equals(src, answer) );
- 标题<pstade/oven/indirected.hpp>
- See: Range Library Proposal.
9.24 jointed
jointedreturns a range which is jointed with its argument
std::string str0("every range"); std::vector<char> str1 = std::string(" is")|copied; std::list<char> str2 = std::string(" string!?")|copied; BOOST_CHECK( oven::equals( str0|jointed(str1)|jointed(str2), std::string("every range is string!?") ) );
- 标题<pstade/oven/jointed.hpp>
- Valid expressionrng1|jointed(rng2)
- Precondition: Theboost::range_referenceofrng2is convertible torng1's without creating a rvalue.
- Returns: A range that joints[boost::begin(rng1),boost::end(rng1))和[boost::begin(rng2),boost::end(rng2)).
9.25 map_keys
map_keysreturns a range whose values are the keys of the base associative container
std::map<int, std::string> m; m[12] = "hello"; m[4] = "map"; m[99] = "keys"; BOOST_FOREACH (int k, m|map_keys) { BOOST_CHECK( k != 12 || m[k] == "hello" ); BOOST_CHECK( k != 4 || m[k] == "map" ); BOOST_CHECK( k != 99 || m[k] == "keys" ); }
- 标题<pstade/oven/map_keys.hpp>
- See: Range Library Proposal.
9.26 map_values
map_valuesreturns a range whose values are the mapped values of the base associative container
std::map<int, std::string> m; m[12] = "hello"; m[4] = "map"; m[99] = "keys"; BOOST_FOREACH (std::string& v, m|map_values) { if (v == "keys") v = "values"; } BOOST_CHECK( m[12] == "hello" ); BOOST_CHECK( m[4] == "map" ); BOOST_CHECK( m[99] == "values" );
- 标题<pstade/oven/map_values.hpp>
- See: Range Library Proposal.
9.27 matches
- 标题<pstade/oven/matches.hpp>; not included by<pstade/oven/ranges.hpp>
- Valid expressionbiRng|matches(re)或biRng|matches(re,flag)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::regex_iterator.
9.28 memoized
memoizedreturns a range whose values are cached for speed, preparing for repeated dereferences
std::stringstream ss; ss << "hello, memoized!"; ::very_complicated_algorithm( oven::stream_input<char>(ss) | memoized | directed | indirected | sorted | memoized );
- 标题<pstade/oven/memoized.hpp>
- Valid expressionrng|memoized和rng|memoized(tb), wheretbis a namedmemo_tableobject.
- Preconditionboost::range_valueofrngisCopyConstructible. tbhas longer lifetime than the use of returned range.
- Returns: A Forward Range whose values are memoized. [12]
[12] | memoizedcan return a Forward Range even if the base range is a Single Pass Range. |
9.29 merged
mergedcombines two sorted ranges into a single sorted range
std::string A1("abbbfH"); std::string A2("ABbCDFFhh"); std::string AA("aAbbbBbCDfFFHhh"); BOOST_CHECK( oven::equals(A1|merged(A2, &::lt_nocase), AA) );
- 标题<pstade/oven/merged.hpp>
- Valid expressionrng1|merged(rng2)和rng1|merged(rng2,pred)
- Preconditionrng1和rng2are sorted.
- Returns: A constant range up to Forward Range which behaves as if they were made bystd::merge.
9.30 permuted
- 标题<pstade/oven/permuted.hpp>
- Valid expressionrndRng|permuted(rng)
- Preconditionrngis a range of the indices ofrndRng.
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::permutation_iterator.
9.31 pointed
pointedprovides an interface to have a conversation with legacy APIs
std::string const src("hello, pointed"); std::vector<char> vec; vec.resize(oven::distance(src) + 1); std::strcpy(boost::begin(vec|pointed), src.c_str()); BOOST_CHECK(( oven::equals(vec|null_terminated, src) ));
- 标题<pstade/oven/pointed.hpp>
- Valid expressionvec|pointed
- Preconditionvecis a template instantiation ofstd::vector.
- Returns[&*boost::begin(vec),&*boost::begin(vec)+oven::distance(vec))ifvecis not empty; otherwise,[0,0).
9.32 popped
- 标题<pstade/oven/popped.hpp>
- Valid expressionfwdRng|popped
- Preconditionboost::empty(fwdRng) == false
- Returns[boost::begin(fwdRng),boost::next(boost::begin(fwdRng),oven::distance(fwdRng)-1))
9.33 prepended
- 标题<pstade/oven/prepended.hpp>
- Valid expressionrng|prepended(v)
- Returns: A range which behaves as if it wereas_single(v)|jointed(rng).
9.34 reversed
- 标题<pstade/oven/reversed.hpp>
- See: Range Library Proposal.
9.35 rotated
- 标题<pstade/oven/rotated.hpp>
- Valid expressionfwdRng|rotated(fun)
- Returns[fun(fwdRng),boost::end(fwdRng))|jointed([boost::begin(fwdRng),fun(fwdRng)))
9.36 scanned
scannedis similar tooven::accumulate, but returns a range of successive reduced values from the base range
int const src[] = { 1,2,3,4,5 }; std::string null; BOOST_FOREACH (std::string str, src|scanned(null, &::stringize)) { std::cout << "\"" << str << "\" "; } // outputs: "" "1" "12" "123" "1234" "12345"
- 标题<pstade/oven/scanned.hpp>
- Valid expressionrng|scanned(init,fun), where the type ofinitisDefaultConstructible, CopyConstructible和CopyAssignable.
- Preconditionfun(s,r)is a valid expression, where the type ofsis the same asinit和ris the iterator dereference ofrng.
- Returns: A range up to Forward Range which behaves as if it were made bystd::partial_sum.
9.37 seconds
- 标题<pstade/oven/seconds.hpp>
- Valid expressionrng|seconds
- Returns: A range which behave as if it wererng|map_values.
9.38 set_cap
- 标题<pstade/oven/set_cap.hpp>
- Valid expressionrng1|set_cap(rng2)和rng1|set_cap(rng2,pred)
- Preconditionrng1和rng2are sorted.
- Returns: A constant range up to Forward Range which behaves as if they were made bystd::set_intersection.
9.39 set_cup
- 标题<pstade/oven/set_cup.hpp>
- Valid expressionrng1|set_cup(rng2)和rng1|set_cup(rng2,pred)
- Preconditionrng1和rng2are sorted.
- Returns: A constant range up to Forward Range which behaves as if they were made bystd::set_union.
9.40 set_delta
- 标题<pstade/oven/set_delta.hpp>
- Valid expressionrng1|set_delta(rng2)和rng1|set_delta(rng2,pred)
- Preconditionrng1和rng2are sorted.
- Returns: A constant range up to Forward Range which behaves as if they were made bystd::set_symmetric_difference.
9.41 set_minus
- 标题<pstade/oven/set_minus.hpp>
- Valid expressionrng1|set_minus(rng2)和rng1|set_minus(rng2,pred)
- Preconditionrng1和rng2are sorted.
- Returns: A constant range up to Forward Range which behaves as if they were made bystd::set_difference.
9.42 shared
shared, taking a pointer to heap-allocated range, makes a range whose iterators manage its lifetime
BOOST_FOREACH (char ch, std::string("dangling")|identities) { // will crash; 'std::string' object doesn't exist anymore. std::cout << ch; } BOOST_FOREACH (char ch, new std::string("ok")|shared|identities) { // works fine. std::cout << ch; }
- 标题<pstade/oven/shared.hpp>
- Valid expressionp|shared
- Preconditionboost::shared_ptris constructible fromp.
- Returns: A range whose iterators behave as if they were the original iterators wrapped in shared_container_iterator.
You can find a more elaborate example at<pstade/oven/sorted.hpp>.
9.43 sliced
sliced[13] provides the column view of the base range
int const answer[] = { 2,6,10,14 }; BOOST_CHECK( oven::equals(answer, counting(0, 16)|sliced(2, 4) ) );
- 标题<pstade/oven/sliced.hpp>
- Valid expressionrndRng|sliced(start,stride)
- Preconditiond == 0 || d % stride == 0和0 <= start && start < stride, whered = oven::distance(rndRng);
[13] | This name is different from Range Library Proposal's, which is the role of advanced or window. |
9.44 string_found
- 标题<pstade/oven/string_found.hpp>
- Valid expressionrng|string_found(finder)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::algorithm::find_iterator.
9.45 string_split
- 标题<pstade/oven/string_split.hpp>
- Valid expressionrng|string_split(finder)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::algorithm::split_iterator.
9.46 taken
taken, applied to the base range, returns the prefix of the range of lengthn:
std::string src("hello, taken!"); std::string ans("hello"); BOOST_CHECK( oven::equals(src|taken(7)|taken(5), ans) );
- 标题<pstade/oven/taken.hpp>
- Valid expressionrng|taken(n)
- Precondition0 <= n
- Returns: A range up to Forward Range which behaves as if it were[boost::begin(rng),boost::next(boost::begin(rng),std::min(n, distance(rng)))).
9.47 taken_while
taken_while, applied to a Predicate and the base range, returns the longest prefix (possibly empty) of the range of elements that satisfy Predicate
std::string src("11111234516313!"); BOOST_CHECK( oven::equals( src|taken_while(lambda::_1 == '1'), std::string("11111") ) );
- 标题<pstade/oven/taken_while.hpp>
- Valid expressionrng|taken_while(pred)
- Returns: A range up to Forward Range which behaves as if it were[boost::begin(rng),oven::find_if(rng,not_(pred)))
9.48 tokenized
- 标题<pstade/oven/tokenized.hpp>; not included by<pstade/oven/ranges.hpp>
- See: Range Library Proposal.
9.49 transformed
- 标题<pstade/oven/transormed.hpp>
- Valid expressionrng|transformed(rfun)
- See: Range Library Proposal.
9.50 uniqued
- 标题<pstade/oven/uniqued.hpp>
- See: Range Library Proposal.
9.51 unzipped
unzippedreverseszipped:
std::cout << ( assign::list_of (boost::make_tuple(1,2)) (boost::make_tuple(2,3)) (boost::make_tuple(3,4)) | unzipped ); // output> ({1,2,3} {2,3,4})
- 标题<pstade/oven/unzipped.hpp>
- Valid expressiontuples|unzipped, wheretuplesis a range whose value_type isboost::tuple.
- Returns: Aboost::tuplewhose elements are unzipped ranges.
9.52 utf8_decoded
- 标题<pstade/oven/utf8_decoded.hpp>
- Valid expressionbiRng|utf8_decoded
- Returns: A Bidirectional Range whose iterators behave as if they were the original iterators wrapped inboost::u8_to_u32_iterator.
9.53 window
- 标题<pstade/oven/window.hpp>
- Valid expressionfwdRng|window(n,m)
- Returns[boost::next(boost::begin(rng),n),boost::next(boost::begin(rng),m)).
9.54 with_position
- 标题<pstade/oven/with_position.hpp>
- Valid expressionrng|with_position
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::spirit::position_iterator.
9.55 xpressive_matches
- 标题<pstade/oven/xpressive_matches.hpp>; not included by<pstade/oven/ranges.hpp>
- Valid expressionbiRng|xpressive_matches(re)或biRng|xpressive_matches(re,flag)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::xpressive::regex_iterator.
9.56 xpressive_tokenized
- 标题<pstade/oven/xpressive_tokenized.hpp>; not included by<pstade/oven/ranges.hpp>
- Valid expressionbiRng|xpressive_tokenized(re)或biRng|xpressive_tokenized(re,subMatches,flag)
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::xpressive::regex_token_iterator.
9.57 zipped
zippedtakes a tuple of ranges and returns a range of corresponding tuples. If one input range is short, excess elements of the longer range are discarded
std::cout << ( boost::make_tuple( assign::list_of(1)(2)(3), assign::list_of(2)(3)(4) ) | zipped ); // output> {(1 2),(2 3),(3 4)}
- 标题<pstade/oven/zipped.hpp>
- Valid expressionrngs|zipped, whererngsis aboost::tupleof ranges.
- Returns: A range whose iterators behave as if they were the original iterators wrapped inboost::zip_iterator.
9.58 zipped_with
zipped_withgeneraliseszippedby zipping with the Function Object, given as the first argument, instead of a tupling
int xs[] = { 0, 1, 2, 3, 4, 5, 6 }; int ys[] = { 1, 6, 1, 2, 7, 8, 3 }; int ans[] = { 1, 7, 3, 5,11,13, 9 }; BOOST_CHECK( oven::equals( boost::tie(xs, ys)|zipped_with(::plus()), ans ) );
- 标题<pstade/oven/zipped_with.hpp>
- Valid expressionrngs|zipped_with(rfun), whererngsis aboost::tupleof ranges.
- Precondition1: The arity ofrfunis the length ofrngs.
- Returns: A range whose values are zipped by usingrfun.
10 Output Iterator Adaptors
10.1 to_counter
to_countertakes an initial count and increments it every output. adapted_to/to_base can extract the result of the counting
int const rng[] = { 0,0,1,1,2,3,3,3,4,4,4,4,4,5,5 }; int i = oven::copy(rng|uniqued, oven::to_counter(0))|to_base; BOOST_CHECK( i == 6 ); BOOST_CHECK( 7 == oven::adapted_to<int>(oven::unique_copy(rng, oven::to_counter(1))) );
- 标题<pstade/oven/to_counter.hpp>
- Valid expressionto_counter(i), whereiis anIncrementable.
- Returns: AnOutputIteratorwhich counts the output.
10.2 to_function
to_functionreturns anOutputIteratorwhich is a port of boost::function_output_iterator with some workarounds.
- 标题<pstade/oven/to_function.hpp>
- Valid expressionto_function(fun)
- Returns: AnOutputIteratorwhich behaves as if it wereboost::function_output_iterator.
10.3 to_stream
to_streamreturns anOutputItertorwhich is a shorthand version ofstd::ostream_iterator. It needs no an explicit template parameter to specify thevalue_typeto output, but one precondition below must be kept. Generally, theboost::iterator_referenceofInputIteratormust be the same asvalue_typeof it except for reference qualifier.
- 标题<pstade/oven/to_stream.hpp>
- Valid expressionto_stream(os)
- Precondition: The type to be assigned to dereference of an iterator whichto_streamreturns must be anOutputStreamable.
- Returns: AnOutputIteratorwhich behave as if it werestd::ostream_iterator.
10.4 to_utf8_encoder
- 标题<pstade/oven/to_utf8_encoder.hpp>
- Valid expressionto_utf8_encoder(oit), whereoitis anOutputIterator.
- Returns: AnOutputIteratorwhich behave as if it wereboost::utf8_output_iterator.
11 Extending Boost.Range
The extension way of Boost.Range seems to assume the future C++ abilitydecltype. For now, it is not practical to apply the way to a large library something like MFC. Oven provides yet another extension way, which is similar to Conceptualizing the Range-Based for Loop proposal to simplify the Boost.Range one
namespace Foo { template< class T > struct Pair { T first, last; }; } // namespace Foo namespace pstade_oven_extension { template< class T > struct Range< Foo::Pair<T> > { // X == Foo::Pair<T> template< class X > struct associate { typedef T mutable_iterator; typedef T constant_iterator; }; // if X is not const, Iterator == mutable_iterator; // otherwise, Iterator == constant_iterator. template< class Iterator, class X > Iterator begin(X& x) { return x.first; } template< class Iterator, class X > Iterator end(X& x) { return x.last; } }; } // namespace pstade_oven_extension PSTADE_OVEN_EXTENSION_OF_TEMPLATE((Foo)(Pair), (class)) // PSTADE_OVEN_EXTENSION_OF_TEMPLATE((Foo)(Pair), 1) // also ok.
- Specialize::pstade_oven_extension::Range.
- Define templateassociate, begin和end.
- Call the macro, in global namespace, to act as a bridge between Oven and Boost.Range.
Note that the const overloads can be sometimes omitted like above. Also,Rangehas the second template parameter forpstade::enable_if. boost::sizeis automatically extended by Oven.
- 标题<pstade/oven/extension.hpp>
- Valid expression1PSTADE_OVEN_EXTENSION_OF_TYPE(X)
- Valid expression2PSTADE_OVEN_EXTENSION_OF_TEMPLATE(X,N), whereNis the number of template arguments. Only valid if all template arguments are typenames.
- Valid expression3PSTADE_OVEN_EXTENSION_OF_TEMPLATE(X,S), whereSis a sequence of template arguments. Must be used when integral or template template parameters are present.
- PreconditionXis a Boost.Preprocessor Sequence of type name.
12 MFC/ATL Extension
Oven provides Boost.Range support for MFC/ATL collection and string types. See Oven Range MFC/ATL Extension.
13 Acknowledgments
14 Release Notes
14.1 Version 0.90.0
- Released initial version.
14.2 Version 0.90.1 - 0.90.6
- Updated this document.
- Implemented Range Algorithms.
- Added some Ranges and Range Adaptors.
- Added some Range Adaptors.
- Changed the header of permuted.
- Changed the header ofpointed.
- Changed a valid expression of zipped.
- Changed checked to throw exception.
- Renamedfoundto string_found.
- Changed the header of Range Algorithms.
- Addedbase_iterator.
- Added some Range Adaptors.
- Renamedaccumulatedto scanned.
- Added workaround for Standard Library Defect #198.
- Changed constants semantics, and added always instead.
- Changed utf8_decoded valid expression.
- shared acceptsauto_ptr.
14.3 Version 0.90.7 - 0.90.9
- Addedmatched, xpressive_matched和xpressive_tokenized.
- Renamedbase_iteratortoto_base.
- Renamedcopiedadaptor tocopied_to.
- Added concatenated.
- Renamedcopied_totocopied_out.
- Fixed a bug oftransformed和concatenated.
- Addedgenerated.
- No longer supports function types asrfun.
- Changed utf8_decoded valid expression.
14.4 Version 0.91.0 - 0.91.3
- Added Output Iterator Adaptors.
- Renamedgeneratedtogeneration.
- Renamedpositionedtowith_position.
- Renamedmatchedtomatches.
- Renamedxpressive_matchedtoxpressive_matches.
- Added Extending Boost.Range.
- 已拒绝out_placed和sorted.
- Addedliteral_range和c_str_range.
- null_terminatedno longer supports c-string.
- Addedas_singletosingle_range's valid expressions.
- Addedbegins/ends.
- Addedmerged, set_cup, set_cap, set_minus和set_delta.
- Addedrotated.
- Removedstriddenand changed effects ofsliced.
- Addedthrough_window.
- Addedpopped.
- Changed the valid expression ofarray_protect_range和literal_range.
- Addedto_function.
- Renamedshiftedtoadvanced.
14.5 Version 0.91.4 - 0.91.9
- Addedany_range.
- Removedpoppedand changed the valid expression ofadvanced.
- Removedgenerationas adaptor and added it as range.
- taken和taken_whilesupports Single Pass Range.
- Addediterate_range.
- Addedadjacent_transformed.
- Addedpopped_back.
- Changedcounting_rangevalid expressions.
- Renamedrepeatedtocycled.
- Addedrepeat_range.
- Renamedpopped_backtopopped.
- Changed the valid expressions ofzipped和zipped_with.
- Ported to VC++7.1 SP1.
- Added MFC/ATL support.
14.6 Version 0.92.0 - 0.92.3
- Renamedcounting_rangetocount_range, and added a valid expression.
- Removed the valid expressionadvanced(d).
- Renamedtietopack.
- Addedboost::result_ofsupport to range-based algorithms.
- Renamed Extending Boost.Range macros.
- Renamedadaptor_totoadapted_to.
14.7 Version 0.93.0
- Changed the names of some functions and headers.
- Addeddelimited.
14.8 Version 0.93.1
- Renamedbegins/endstobegin/end.
- adjacent_transformedrejects empty range.
- Changed template parameter ofany_range.
- Replacedregularized用regular.
- Removedto_regularized_function.
- scannedrange contains theinitas the first element.
14.9 Version 0.93.2
- taken和taken_whilebehave lazily.
- taken和taken_whilenow return only up to ForwardRange.
- dropped和takenacceptnwhich is larger than the distance.
- Removednull_terminated.
- as_c_straccepts a range.
- zipped和zipped_withaccept any tuple.
- Removedgeneration_copied.
- Addedshared_regular和innumerable.
14.10 Version 0.93.3
- Fixed a bug ofgeneration.
- Addedfront和back.
- Addedrecursion.