add range/adaptor/transformed

This commit is contained in:
bolero-MURAKAMI 2012-04-30 17:30:47 +09:00
parent 3e5facb754
commit 3ff16b4054
8 changed files with 743 additions and 41 deletions

View file

@ -58,36 +58,38 @@ namespace sprout {
struct placeholder {};
namespace placeholders {
SPROUT_STATIC_CONSTEXPR sprout::placeholder<1> _1;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<2> _2;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<3> _3;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<4> _4;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<5> _5;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<6> _6;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<7> _7;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<8> _8;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<9> _9;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<10> _10;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<11> _11;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<12> _12;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<13> _13;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<14> _14;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<15> _15;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<16> _16;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<17> _17;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<18> _18;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<19> _19;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<20> _20;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<21> _21;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<22> _22;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<23> _23;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<24> _24;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<25> _25;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<26> _26;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<27> _27;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<28> _28;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<29> _29;
SPROUT_STATIC_CONSTEXPR sprout::placeholder<30> _30;
namespace {
SPROUT_STATIC_CONSTEXPR sprout::placeholder<1> _1{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<2> _2{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<3> _3{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<4> _4{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<5> _5{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<6> _6{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<7> _7{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<8> _8{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<9> _9{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<10> _10{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<11> _11{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<12> _12{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<13> _13{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<14> _14{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<15> _15{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<16> _16{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<17> _17{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<18> _18{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<19> _19{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<20> _20{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<21> _21{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<22> _22{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<23> _23{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<24> _24{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<25> _25{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<26> _26{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<27> _27{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<28> _28{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<29> _29{};
SPROUT_STATIC_CONSTEXPR sprout::placeholder<30> _30{};
} // anonymous-namespace
} // namespace placeholders
using sprout::placeholders::_1;
using sprout::placeholders::_2;

View file

@ -162,10 +162,10 @@ namespace sprout {
return !(lhs < rhs);
}
template<typename Iterator1, typename Iterator2>
SPROUT_CONSTEXPR auto operator-(
SPROUT_CONSTEXPR decltype(std::declval<Iterator1>() - std::declval<Iterator2>()) operator-(
sprout::reverse_iterator<Iterator1> const& lhs,
sprout::reverse_iterator<Iterator2> const& rhs
) -> decltype(lhs.base() - rhs.base())
)
{
return lhs.base() - rhs.base();
}

View file

@ -0,0 +1,441 @@
#ifndef SPROUT_ITERATOR_TRANSFORM_ITERATOR_HPP
#define SPROUT_ITERATOR_TRANSFORM_ITERATOR_HPP
#include <iterator>
#include <utility>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/next.hpp>
#include <sprout/iterator/prev.hpp>
#include <sprout/iterator/distance.hpp>
namespace sprout {
//
// transform_iterator
//
template<typename BinaryFunction, typename LIterator, typename RIterator = void>
class transform_iterator
: public std::iterator<
typename std::iterator_traits<LIterator>::iterator_category,
typename std::remove_reference<
typename std::result_of<
BinaryFunction (
typename std::iterator_traits<LIterator>::reference,
typename std::iterator_traits<RIterator>::reference
)
>::type
>::type,
typename std::iterator_traits<LIterator>::difference_type,
typename std::remove_reference<
typename std::result_of<
BinaryFunction (
typename std::iterator_traits<LIterator>::reference,
typename std::iterator_traits<RIterator>::reference
)
>::type
>::type*,
typename std::result_of<
BinaryFunction (
typename std::iterator_traits<LIterator>::reference,
typename std::iterator_traits<RIterator>::reference
)
>::type
>
{
public:
typedef BinaryFunction functor_type;
typedef LIterator iterator_type;
typedef RIterator iterator2_type;
typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
typedef typename std::result_of<
BinaryFunction (
typename std::iterator_traits<LIterator>::reference,
typename std::iterator_traits<RIterator>::reference
)
>::type reference;
typedef typename std::remove_reference<reference>::type value_type;
typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
typedef value_type* pointer;
protected:
iterator_type current;
iterator2_type current2;
functor_type func;
public:
transform_iterator() = default;
transform_iterator(transform_iterator const&) = default;
SPROUT_CONSTEXPR transform_iterator(iterator_type it, iterator2_type it2)
: current(it)
, current2(it2)
{}
SPROUT_CONSTEXPR transform_iterator(iterator_type it, iterator2_type it2, functor_type func)
: current(it)
, current2(it2)
, func(func)
{}
template<typename U, typename V, typename W>
SPROUT_CONSTEXPR transform_iterator(transform_iterator<U, V, W> const& it)
: current(it.current)
, current2(it.current2)
, func(it.func)
{}
template<typename U, typename V, typename W>
transform_iterator& operator=(transform_iterator<U, V, W> const& it) {
transform_iterator temp(it);
temp.swap(*this);
return *this;
}
SPROUT_CONSTEXPR iterator_type base() const {
return current;
}
SPROUT_CONSTEXPR iterator_type base2() const {
return current2;
}
SPROUT_CONSTEXPR functor_type functor() const {
return func;
}
SPROUT_CONSTEXPR reference operator*() const {
return func(*current, *current2);
}
SPROUT_CONSTEXPR pointer operator->() const {
return &func(*current, *current2);
}
transform_iterator& operator++() {
++current;
++current2;
return *this;
}
transform_iterator operator++(int) {
transform_iterator result(*this);
++current;
++current2;
return result;
}
transform_iterator& operator--() {
--current;
--current2;
return *this;
}
transform_iterator operator--(int) {
transform_iterator temp(*this);
--current;
--current2;
return temp;
}
SPROUT_CONSTEXPR transform_iterator operator+(difference_type n) const {
return transform_iterator(current + n, current2 + n, func);
}
SPROUT_CONSTEXPR transform_iterator operator-(difference_type n) const {
return transform_iterator(current - n, current2 - n, func);
}
transform_iterator& operator+=(difference_type n) {
transform_iterator temp(current + n, current2 + n, func);
temp.swap(*this);
return *this;
}
transform_iterator& operator-=(difference_type n) {
transform_iterator temp(current - n, current2 - n, func);
temp.swap(*this);
return *this;
}
SPROUT_CONSTEXPR reference operator[](difference_type n) const {
return func(current[n], current2[n]);
}
SPROUT_CONSTEXPR transform_iterator next() const {
return transform_iterator(sprout::next(current), sprout::next(current2), func);
}
SPROUT_CONSTEXPR transform_iterator prev() const {
return transform_iterator(sprout::prev(current), sprout::prev(current2), func);
}
void swap(transform_iterator& other) {
using std::swap;
swap(current, other.current);
swap(current2, other.current2);
swap(func, other.func);
}
};
//
// transform_iterator
//
template<typename UnaryFunction, typename Iterator>
class transform_iterator<UnaryFunction, Iterator, void>
: public std::iterator<
typename std::iterator_traits<Iterator>::iterator_category,
typename std::remove_reference<
typename std::result_of<
UnaryFunction (typename std::iterator_traits<Iterator>::reference)
>::type
>::type,
typename std::iterator_traits<Iterator>::difference_type,
typename std::remove_reference<
typename std::result_of<
UnaryFunction (typename std::iterator_traits<Iterator>::reference)
>::type
>::type*,
typename std::result_of<
UnaryFunction (typename std::iterator_traits<Iterator>::reference)
>::type
>
{
public:
typedef UnaryFunction functor_type;
typedef Iterator iterator_type;
typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
typedef typename std::result_of<
UnaryFunction (typename std::iterator_traits<Iterator>::reference)
>::type reference;
typedef typename std::remove_reference<reference>::type value_type;
typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
typedef value_type* pointer;
protected:
iterator_type current;
functor_type func;
public:
transform_iterator() = default;
transform_iterator(transform_iterator const&) = default;
explicit SPROUT_CONSTEXPR transform_iterator(iterator_type it)
: current(it)
{}
SPROUT_CONSTEXPR transform_iterator(iterator_type it, functor_type func)
: current(it)
, func(func)
{}
template<typename U, typename V>
SPROUT_CONSTEXPR transform_iterator(transform_iterator<U, V> const& it)
: current(it.current)
, func(it.func)
{}
template<typename U, typename V>
transform_iterator& operator=(transform_iterator<U, V> const& it) {
transform_iterator temp(it);
temp.swap(*this);
return *this;
}
SPROUT_CONSTEXPR iterator_type base() const {
return current;
}
SPROUT_CONSTEXPR functor_type functor() const {
return func;
}
SPROUT_CONSTEXPR reference operator*() const {
return func(*current);
}
SPROUT_CONSTEXPR pointer operator->() const {
return &func(*current);
}
transform_iterator& operator++() {
++current;
return *this;
}
transform_iterator operator++(int) {
transform_iterator result(*this);
++current;
return result;
}
transform_iterator& operator--() {
--current;
return *this;
}
transform_iterator operator--(int) {
transform_iterator temp(*this);
--current;
return temp;
}
SPROUT_CONSTEXPR transform_iterator operator+(difference_type n) const {
return transform_iterator(current + n, func);
}
SPROUT_CONSTEXPR transform_iterator operator-(difference_type n) const {
return transform_iterator(current - n, func);
}
transform_iterator& operator+=(difference_type n) {
transform_iterator temp(current + n, func);
temp.swap(*this);
return *this;
}
transform_iterator& operator-=(difference_type n) {
transform_iterator temp(current - n, func);
temp.swap(*this);
return *this;
}
SPROUT_CONSTEXPR reference operator[](difference_type n) const {
return func(current[n]);
}
SPROUT_CONSTEXPR transform_iterator next() const {
return transform_iterator(sprout::next(current), func);
}
SPROUT_CONSTEXPR transform_iterator prev() const {
return transform_iterator(sprout::prev(current), func);
}
void swap(transform_iterator& other) {
using std::swap;
swap(current, other.current);
swap(func, other.func);
}
};
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator==(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return lhs.base() == rhs.base();
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator!=(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return !(lhs == rhs);
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator<(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return lhs.base() < rhs.base();
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator>(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return rhs < lhs;
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator<=(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return !(rhs < lhs);
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR bool operator>=(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return !(lhs < rhs);
}
template<
typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1,
typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2
>
SPROUT_CONSTEXPR decltype(std::declval<LIterator1>() - std::declval<LIterator2>()) operator-(
sprout::transform_iterator<UnaryOrBinaryFunction1, LIterator1, RIterator1> const& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction2, LIterator2, RIterator2> const& rhs
)
{
return lhs.base() - rhs.base();
}
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> operator+(
typename sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator>::difference_type n,
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> const& it
)
{
return it + n;
}
//
// make_transform_iterator
//
template<typename BinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<BinaryFunction, LIterator, RIterator>
make_transform_iterator(LIterator it1, RIterator it2, BinaryFunction func) {
return sprout::transform_iterator<BinaryFunction, LIterator, RIterator>(it1, it2, func);
}
template<typename UnaryFunction, typename Iterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryFunction, Iterator>
make_transform_iterator(Iterator it, UnaryFunction func) {
return sprout::transform_iterator<UnaryFunction, Iterator>(it, func);
}
//
// swap
//
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
void swap(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator>& lhs,
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator>& rhs
)
SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs)))
{
lhs.swap(rhs);
}
//
// next
//
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> next(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> const& it
)
{
return it.next();
}
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> next(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> const& it,
typename sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator>::difference_type n
)
{
return it + n;
}
//
// prev
//
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> prev(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> const& it
)
{
return it.prev();
}
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> prev(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> const& it,
typename sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator>::difference_type n
)
{
return it - n;
}
//
// distance
//
template<typename UnaryOrBinaryFunction, typename LIterator, typename RIterator>
SPROUT_CONSTEXPR typename std::iterator_traits<sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> >::difference_type
distance(
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> first,
sprout::transform_iterator<UnaryOrBinaryFunction, LIterator, RIterator> last
)
{
return last - first;
}
} // namespace sprout
#endif // #ifndef SPROUT_ITERATOR_TRANSFORM_ITERATOR_HPP

View file

@ -192,7 +192,7 @@ namespace sprout {
Args&&... args
)
{
return sprout::remake<Container>(sprout::forward<Cont>(cont), size, sprout::forward<Args>(args)...);
return sprout::remake<copied_type>(sprout::forward<Cont>(cont), size, sprout::forward<Args>(args)...);
}
};

7
sprout/range/adaptor.hpp Normal file
View file

@ -0,0 +1,7 @@
#ifndef SPROUT_RANGE_ADAPTOR_HPP
#define SPROUT_RANGE_ADAPTOR_HPP
#include <sprout/config.hpp>
#include <sprout/range/adaptor/transformed.hpp>
#endif // #ifndef SPROUT_RANGE_ADAPTOR_HPP

View file

@ -0,0 +1,226 @@
#ifndef SPROUT_RANGE_ADAPTOR_TRANSFORMD_HPP
#define SPROUT_RANGE_ADAPTOR_TRANSFORMD_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/pit.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/iterator/transform_iterator.hpp>
#include <sprout/range/range_container.hpp>
#include <sprout/range/algorithm/copy.hpp>
#include <sprout/type_traits/lvalue_reference.hpp>
#include <sprout/utility/forward.hpp>
#include <sprout/utility/lvalue_forward.hpp>
#include <sprout/utility/value_holder.hpp>
namespace sprout {
namespace range {
//
// transformed_range
//
template<typename BinaryFunction, typename LRange, typename RRange = void>
class transformed_range
: public sprout::range::range_container<
sprout::transform_iterator<
BinaryFunction,
typename sprout::container_traits<LRange>::iterator,
typename sprout::container_traits<RRange>::iterator
>
>
, public sprout::detail::inherit_if_fixed_size<LRange>
{
public:
typedef BinaryFunction functor_type;
typedef LRange range_type;
typedef RRange range2_type;
typedef sprout::range::range_container<
sprout::transform_iterator<
BinaryFunction,
typename sprout::container_traits<LRange>::iterator,
typename sprout::container_traits<RRange>::iterator
>
> base_type;
typedef typename base_type::iterator iterator;
typedef typename base_type::size_type size_type;
public:
transformed_range() = default;
transformed_range(transformed_range const&) = default;
SPROUT_CONSTEXPR transformed_range(functor_type func, range_type& range1, range2_type& range2)
: base_type(
iterator(sprout::begin(range1), sprout::begin(range2), func),
iterator(sprout::end(range1), sprout::end(range2), func)
)
{}
};
template<typename UnaryFunction, typename Range>
class transformed_range<UnaryFunction, Range, void>
: public sprout::range::range_container<
sprout::transform_iterator<
UnaryFunction,
typename sprout::container_traits<Range>::iterator
>
>
, public sprout::detail::inherit_if_fixed_size<Range>
{
public:
typedef UnaryFunction functor_type;
typedef Range range_type;
typedef sprout::range::range_container<
sprout::transform_iterator<
UnaryFunction,
typename sprout::container_traits<Range>::iterator
>
> base_type;
typedef typename base_type::iterator iterator;
public:
transformed_range() = default;
transformed_range(transformed_range const&) = default;
SPROUT_CONSTEXPR transformed_range(functor_type func, range_type& range)
: base_type(
iterator(sprout::begin(range), func),
iterator(sprout::end(range), func)
)
{}
};
//
// transform_holder
//
template<typename BinaryFunction, typename RRange = void>
class transform_holder {
public:
typedef BinaryFunction functor_type;
typedef RRange range2_type;
private:
functor_type func_;
sprout::value_holder<range2_type&> range_;
public:
transform_holder() = default;
transform_holder(transform_holder const&) = default;
SPROUT_CONSTEXPR transform_holder(functor_type func, range2_type& range)
: func_(func)
, range_(range)
{}
SPROUT_CONSTEXPR functor_type functor() const {
return func_;
}
SPROUT_CONSTEXPR range2_type& range() const {
return range_;
}
};
template<typename UnaryFunction>
class transform_holder<UnaryFunction, void> {
public:
typedef UnaryFunction functor_type;
private:
functor_type func_;
public:
transform_holder() = default;
transform_holder(transform_holder const&) = default;
explicit SPROUT_CONSTEXPR transform_holder(functor_type func)
: func_(func)
{}
SPROUT_CONSTEXPR functor_type functor() const {
return func_;
}
};
//
// transformed_forwarder
//
class transformed_forwarder {
public:
template<typename RRange, typename BinaryFunction>
SPROUT_CONSTEXPR sprout::range::transform_holder<
BinaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<RRange>::type>::type
>
operator()(RRange&& range, BinaryFunction func) {
return sprout::range::transform_holder<
BinaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<RRange>::type>::type
> (
func,
sprout::lvalue_forward<RRange>(range)
);
}
template<typename UnaryFunction>
SPROUT_CONSTEXPR sprout::range::transform_holder<UnaryFunction>
operator()(UnaryFunction func) {
return sprout::range::transform_holder<UnaryFunction>(func);
}
};
//
// transformed
//
namespace {
SPROUT_STATIC_CONSTEXPR sprout::range::transformed_forwarder transformed{};
} // anonymous-namespace
//
// operator|
//
template<typename LRange, typename BinaryFunction, typename RRange>
inline SPROUT_CONSTEXPR sprout::range::transformed_range<
BinaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<LRange>::type>::type,
RRange
>
operator|(LRange&& lhs, sprout::range::transform_holder<BinaryFunction, RRange> const& rhs) {
return sprout::range::transformed_range<
BinaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<LRange>::type>::type,
RRange
>(
rhs.functor(),
sprout::lvalue_forward<LRange>(lhs),
rhs.range()
);
}
template<typename Range, typename UnaryFunction>
inline SPROUT_CONSTEXPR sprout::range::transformed_range<
UnaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<Range>::type>::type
>
operator|(Range&& lhs, sprout::range::transform_holder<UnaryFunction> const& rhs) {
return sprout::range::transformed_range<
UnaryFunction,
typename std::remove_reference<typename sprout::lvalue_reference<Range>::type>::type
>(
rhs.functor(),
sprout::lvalue_forward<Range>(lhs)
);
}
} // namespace range
//
// container_construct_traits
//
template<typename UnaryOrBinaryFunction, typename LRange, typename RRange>
struct container_construct_traits<sprout::range::transformed_range<UnaryOrBinaryFunction, LRange, RRange> > {
public:
typedef typename sprout::container_construct_traits<LRange>::copied_type copied_type;
public:
template<typename Cont>
static SPROUT_CONSTEXPR copied_type deep_copy(Cont&& cont) {
return sprout::range::fixed::copy(sprout::forward<Cont>(cont), sprout::pit<copied_type>());
}
template<typename... Args>
static SPROUT_CONSTEXPR copied_type make(Args&&... args) {
return sprout::make<copied_type>(sprout::forward<Args>(args)...);
}
template<typename Cont, typename... Args>
static SPROUT_CONSTEXPR copied_type remake(
Cont&& cont,
typename sprout::container_traits<sprout::range::transformed_range<UnaryOrBinaryFunction, LRange, RRange> >::difference_type size,
Args&&... args
)
{
return sprout::remake<copied_type>(sprout::forward<Cont>(cont), size, sprout::forward<Args>(args)...);
}
};
} // namespace sprout
#endif // #ifndef SPROUT_RANGE_ADAPTOR_TRANSFORMD_HPP

View file

@ -6,6 +6,7 @@
#include <sprout/config.hpp>
#include <sprout/container/traits.hpp>
#include <sprout/container/functions.hpp>
#include <sprout/range/lvalue_iterator.hpp>
namespace sprout {
namespace range {

View file

@ -13,27 +13,52 @@ namespace sprout {
namespace detail {
template<std::size_t Index, typename Head, bool IsEmpty>
class head_base;
//!!!
// EBO disabled
// template<std::size_t Index, typename Head>
// class head_base<Index, Head, true>
// : public Head
// {
// public:
// static SPROUT_CONSTEXPR Head& head(head_base& t) SPROUT_NOEXCEPT {
// return t;
// }
// static SPROUT_CONSTEXPR Head const& head(head_base const& t) SPROUT_NOEXCEPT {
// return t;
// }
// public:
// SPROUT_CONSTEXPR head_base()
// : Head()
// {}
// SPROUT_CONSTEXPR head_base(Head const& v)
// : Head(v)
// {}
// template<typename UHead>
// SPROUT_CONSTEXPR head_base(UHead&& v)
// : Head(sprout::forward<UHead>(v))
// {}
// };
template<std::size_t Index, typename Head>
class head_base<Index, Head, true>
: public Head
{
class head_base<Index, Head, true> {
public:
static SPROUT_CONSTEXPR Head& head(head_base& t) SPROUT_NOEXCEPT {
return t;
return t.head_;
}
static SPROUT_CONSTEXPR Head const& head(head_base const& t) SPROUT_NOEXCEPT {
return t;
return t.head_;
}
private:
Head head_;
public:
SPROUT_CONSTEXPR head_base()
: Head()
: head_()
{}
SPROUT_CONSTEXPR head_base(Head const& v)
: Head(v)
: head_(v)
{}
template<typename UHead>
SPROUT_CONSTEXPR head_base(UHead&& v)
: Head(sprout::forward<UHead>(v))
: head_(sprout::forward<UHead>(v))
{}
};
template<std::size_t Index, typename Head>