Oven provides many useful predefined ranges.
Though Oven supports Boost.ResultOf,
it is often cumbersome to get the type of the adapted range. any_range
behaves as the type erasure of
ranges.
<pstade/oven/any_range.hpp>
C
.
Valid expression |
Semantics |
---|---|
|
|
|
|
boost::range_reference<_typeof(_rng)>::type
is convertible to R
without binding reference
to rvalue.
C
is convertible to boost::single_pass_traversal_tag
.
boost::range_traversal<_typeof(_rng)>::type
is convertible to C
.
_rng0
is a range returned
from Oven Function
Object and meets the preconditions of _rng
.
any_range<int, boost::single_pass_traversal_tag> factorials = counting(1, 500) | scanned(1, regular(lambda::_1 * lambda::_2));
Iterators of Random
Access any_range
may require heap allocation to copy, whereas any_indexed
offers lightweight-copyable iterators in return for some extra preconditions.
<pstade/oven/any_indexed.hpp>
Valid expression |
Semantics |
---|---|
|
|
array_range
is a noncopyable
Random
Access Range
which delivers a range presentation of dynamically allocated arrays.
<pstade/oven/array_range.hpp>
Valid expression |
Semantics |
---|---|
|
|
new T[sz]
is a valid expression.
std::string str("hello, array_range!"); boost::array<char, 19> sarr; copy(str, sarr|begin); array_range<char> darr(19); copy(str, darr|begin); BOOST_CHECK( equals(sarr, darr) );
directory_range
is a Single
Pass Range
which accesses the contents of a directory.
<pstade/oven/directory_range.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
|
|
T
is boost::filesystem::basic_directory_iterator<P>
such that T(p)
is a valid expression.
BOOST_FOREACH ( boost::filesystem::path const& pt, directory_range(boost::filesystem::current_path())) { std::cout << pt.leaf() << std::endl; }
empty_range
is a Random
Access Range
which is always empty.
<pstade/oven/empty_range.hpp>
Valid expression |
Semantics |
---|---|
|
|
BOOST_CHECK( boost::empty(empty_range<int>()) );
file_range
is a Random
Access Constant
Range
for files. If the file opening failed, the range is empty.
Note | |
---|---|
|
<pstade/oven/file_range.hpp>
r
is a file_range<X1,...,XN>
.
Valid expression |
Semantics |
---|---|
|
|
|
Returns |
!r.is_open() ? boost::empty(r)
: true
T
is boost::spirit::file_iterator<X1,...,XN>
such that T(s)
is a valid expression.
Note | |
---|---|
In the current implementation, an empty file is not opened. So
|
std::vector<char> vec; file_range<char> frng("data.txt"); copy(frng, std::back_inserter(vec));
Some versions of Boost.Range
regard char
array as literal,
which as_array
works around.
<pstade/oven/as_array.hpp>
Valid expression |
Semantics |
---|---|
|
a
is an array.
BOOST_CHECK( distance(as_array("abc\0de")) == 7 ); // contains the trailing null. BOOST_CHECK( distance(as_c_str("abc\0de")) == 3 ); // null means the end. BOOST_CHECK( distance(as_literal("abc\0de")) == 6 ); // null doesn't affect.
as_c_str
makes a Random
Access Range
from null-terminated c-style string.
<pstade/oven/as_c_str.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
_typeof(s)
is
convertible to char *
or char const
*
.
_typeof(_rng)
is neither convertible to char *
nor char
const *
.
as_literal
makes a Random
Access Range
from character array.
<pstade/oven/as_literal.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
a
is an array.
x
is not an array.
Important | |
---|---|
|
block
makes a Single
Pass Range
from an Iteration Block.
<pstade/oven/block.hpp>
yield
is an unspecified
unary Function Object
passed to b
.
Valid expression |
Semantics |
---|---|
|
A Single
Pass Range
whose values are the objects passed to |
b
is an Iteration
Block.
struct power { int m_number, m_exponent; power(int number, int exponent) : m_number(number), m_exponent(exponent) { } typedef int yield_type; template<typename Yield> void operator()(Yield yield) const { int counter = 0; int result = 1; while (counter++ < m_exponent) { result = result * m_number; yield(result); } } }; void test() { power(2, 8)(std::cout << boost::lambda::_1 << ','); BOOST_FOREACH (int x, block(power(2, 8))) std::cout << x << ','; }
Pending... comprehension
emulates set-builder notation.
<pstade/oven/comprehension.hpp>
d(I) =
distance(_rngI)
a(1,j)
ia a j
-th
element of makerng1()
.
I >=
2
, a(I,j)
is
a j
-th element of makerngI(a(I-1,
u))
.
Valid expression |
Semantics |
---|---|
|
A Forward
Lvalue
Constant |
|
|
|
|
|
|
Note | |
---|---|
A result object of
|
N <=
3
_fun
is a N
-ary Polymorphic
Function Object or Boost.Lambda
functor.
_typeof(_fun(...))
is Copy Constructible.
I
, makerngI
is a I-1
-ary Polymorphic
Function Object or Boost.Lambda
functor which returns a Range.
_prd
is N
-ary.
_typeof(b)
is
bool
.
namespace bll = boost::lambda; typedef boost::tuple<int, int, int> triple_t; struct make_triple { typedef triple_t result_type; result_type operator()(int x, int y, int z) const { return result_type(x, y, z); } }; typedef any_range<triple_t, boost::forward_traversal_tag> triples_t; triples_t triples(int n) { return comprehension( ::make_triple(), bll::_1 * bll::_1 + bll::_2 * bll::_2 == bll::_3 * bll::_3, // guard bll::bind(counting, 1, n + 1), // -> _1 bll::bind(counting, bll::_1, n + 1), // -> _2 bll::bind(counting, bll::_2, n + 1) // -> _3 ); } void test() { std::stringstream sout; sout << ::triples(20); BOOST_CHECK(sout.str() == "{(3 4 5),(5 12 13),(6 8 10),(8 15 17),(9 12 15),(12 16 20)}"); }
counting
makes a boost::counting_iterator
range, which is not a
Lvalue
Range.
<pstade/oven/counting.hpp>
Valid expression |
Semantics |
---|---|
|
A Major Function Object type |
|
|
|
|
|
|
0 <=
N &&
N <=
2
T
is boost::counting_iterator<_typeof(j),
X1,...,XN>
such that T(i)
and
T(j)
is
a valid expression.
int ans[] = { 2, 3, 4, 5, 6 }; BOOST_CHECK( equal(counting(2, 7), ans) ); std::vector<int> vec; BOOST_FOREACH (int i, counting(0, 5)) { vec.push_back(i); }
generation
makes a Single
Pass Range
from a Stoppable Generator.
<pstade/oven/generation.hpp>
Valid expression |
Semantics |
---|---|
|
The longest Single
Pass |
g
is a nullary Stoppable
Generator.
g
is Assignable.
_typeof(*g())
is Copy Constructible
and Assignable.
struct rand_generator { typedef boost::optional<long> result_type; result_type operator()() { long result = std::rand(); if (result % 3 == 0) return result_type(); // stop generating. return result; } }; void test() { rand_generator X; BOOST_FOREACH (long x, generation(X)) { std::cout << x << std::endl; } }
hetero
runs through a "tuple".
<pstade/oven/hetero.hpp>
N
is boost::fusion::result_of::size<_typeof(tup)>::type::value
.
Valid expression |
Semantics |
---|---|
|
A Major Function Object type |
|
A Random
Access |
|
|
tup
is a Fusion
Forward Sequence or boost::tuple<...>
.
0 <=
N &&
N <
20
.
I
such that 0 <= I &&
I <
N
, Ref
is convertible to boost::fusion::result_of::at_c<_typeof(tup), I>::type
without binding a reference to rvalue.
rectangle r; triangle t; circle c; boost::tuple<rectangle*, triangle*, circle*> tup(&r, &t, &c); BOOST_FOREACH (shape *s, oven::hetero<shape *>(tup)) { s->draw(); }
initial_values
emulates initializer-lists.
<pstade/oven/initial_values.hpp>
Valid expression |
Semantics |
---|---|
|
A Major Function Object type |
|
A Random
Access Readable
Lvalue
Constant |
|
|
|
|
|
|
Note | |
---|---|
Every
|
1 <=
N &&
N <=
20
_typeof(aK)
is
Copy Constructible
for all K
such that 1 <= K &&
K <=
N
.
_typeof(aK)
is
convertible to _typeof(a1)
for all K
such that 2 <= K &&
K <=
N
.
Rng rng
= X_initial_values<T>()(a1,...,aN)|copied;
is a valid expression.
Rng2 rng2(X_initial_values<T>()(a1,...,aN)|copied);
is a valid expression.
Tip | |
---|---|
|
int const ans[] = { 1,5,3,6,1,3,7,1,4,2,2 }; std::vector<int> vec = initial_values(1,5,3,6,1,3,7,1,4,2,2); BOOST_CHECK( equals(vec, ans) );
iteration
makes an infinite
Forward
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.
Note | |
---|---|
Strictly speaking, the 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.
|
<pstade/oven/iteration.hpp>
just
is an imaginary function
object such that y ->
boost::optional<_typeof(x)>(y)
.
Valid expression |
Semantics |
---|---|
|
|
int answer[] = { 1,2,4,8,16 }; BOOST_CHECK( equals(answer, iteration(1, regular(boost::lambda::_1 * 2))|taken(5) ) );
Types defined in Oven is so hardhead that you can't copy-initialize
any_range
by third-party
ranges. So, you sometimes have to call make_range
,
which turns a range into Oven compatible iterator-range.
<pstade/oven/make_range.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
Pending... recursion
, collaborating
with any_range, creates a recursive
range.
<pstade/oven/recursion.hpp>
Valid expression |
Semantics |
---|---|
|
An up-to-Bidirectional
|
_fwdrng
is an any_range
.
memoized
in the base
range takes its own memo_table
object.
typedef any_range<int const&, boost::forward_traversal_tag> range_t; range_t fibs; memo_table tb; int const start[] = { 1, 1 }; fibs = start | rvalues // for jointed precondition | jointed( boost::make_tuple(recursion(fibs), recursion(fibs)|dropped(1)) | zipped_with(regular(boost::lambda::_1 + boost::lambda::_2)) ) | memoized(tb) ; std::cout << (fibs|taken(howMany));
Note | |
---|---|
In a recursive range,
|
shared
makes a range from
a pointer to a heap allocated range, and the iterators manage the allocation.
<pstade/oven/shared.hpp>
shared_range_iterator
is
an imaginary iterator which works like boost::shared_container_iterator
but uses a range instead of a container.
Valid expression |
Semantics |
---|---|
|
|
sp
is a boost::shared_ptr<_typeof(*p)>(p)
such
that sp(p)
is
a valid expression.
T
is a shared_range_iterator<_typeof(*p)>
such that T(_begin(*p), sp)
is
a valid expression.
BOOST_FOREACH (char ch, std::string("dangling")|identities) { // will crash; 'std::string' object doesn't exist anymore. std::cout << ch; } BOOST_FOREACH (char ch, shared(new std::string("ok"))|identities) { // works fine. std::cout << ch; }
single
makes a Random
Access Range
which delivers a range presentation of one object.
<pstade/oven/single.hpp>
Valid expression |
Semantics |
---|---|
|
|
Note | |
---|---|
As the semantics implies, the iterators are valid as long as
|
BOOST_CHECK( equals(single('a'), std::string("a")) );
shared_single
, given a pointer
to a heap allocated object, delivers a range presentation of the pointee.
<pstade/oven/shared_single.hpp>
Valid expression |
Semantics |
---|---|
|
|
boost::shared_ptr<_typeof(*p)>(p)
is
a valid expression.
boost::result_of<T_shared_single(char *)>::type make_rng() { return shared_single(new char('a')); }
stream_lines
makes a std::string
Single
Pass Range
from std::cout
etc.
<pstade/oven/stream_lines.hpp>
DefaultA
is std::allocator<_typeof(s)::char_type>
.
Valid expression |
Semantics |
---|---|
|
A Major Function Object type |
|
|
|
|
T
is hamigaki::istream_line_iterator<_typeof(s)::char_type,
_typeof(s)::traits_type,
A>
suct that T(s)
is
a valid expression.
stream_read
makes a Single
Pass Range
from std::cout
etc.
<pstade/oven/stream_read.hpp>
Valid expression |
Semantics |
---|---|
|
A Major Function Object type |
|
|
|
|
Important | |
---|---|
Notice that
|
T
is std::istream_iterator<V, _typeof(s)::char_type,
_typeof(s)::traits_type,
D>
suct that T(s)
is
a valid expression.
std::string src("hello,stream_read!"); std::stringstream ss; ss << src; std::string result; copy(oven::stream_read<char>(ss), std::back_inserter(result)); BOOST_CHECK( equals(result, src) );
<pstade/oven/stream_read.hpp>
Valid expression |
Semantics |
---|---|
|
|
|
|
T
is std::istreambuf_iterator<_typeof(s)::char_type,
_typeof(s)::traits_type>
such that T(s)
is
a valid expression.
U
is std::istreambuf_iterator<_typeof(*p)::char_type,
_typeof(*p)::traits_type>
such that U(p)
is
a valid expression.
unfold
makes a range from
a seed.
<pstade/oven/unfold.hpp>
Valid expression |
Semantics |
---|---|
|
The longest Forward
|
Note | |
---|---|
|
z
, f(...)
and g
is Assignable,
Copy Constructible
and Default
Constructible.
f
is a unary Stoppable
Generator.
g
is a Function
Object such that z1 = g(z1)
is
well-formed, where _typeof(z)
z1 =
z
.
f
and g
is a mapping,
meaning that a ==
b
implies f(a)
== f(b)
.
boost::optional<int> mod(int i) { if (i == 0) return boost::optional<int>(); return i % 10; } void test() { int const answer[] = { 1,5,4,1,9,2,3,6,1 }; BOOST_CHECK( equals(unfold(163291451, &mod, lambda::_1 / 10), answer) ); }
Copyright © 2005 -2007 Shunsuke Sogame |