From fce71b6e7623b29349f9a6be2ffd82167b73c887 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 28 Sep 2014 20:41:00 -0400 Subject: [PATCH 001/596] uses -std=c++14 in SConstruct --- tests/SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SConstruct b/tests/SConstruct index eb1c70a7..7a4abeec 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -4,7 +4,7 @@ import os env = Environment( CXX='c++', CXXFLAGS= ['-g', '-Wall', '-Wextra', - '-pedantic', '-std=c++11', + '-pedantic', '-std=c++14', '-fdiagnostics-color=always', '-I/usr/local/include'], CPPPATH='..', From 84d382bda543af17f30371ca53cc5a3730dace8e Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 28 Sep 2014 20:41:07 -0400 Subject: [PATCH 002/596] Flattens zip implementation No recursive template. Using std::index_sequence everywhere now. --- zip.hpp | 137 ++++++++++++++++++++++++-------------------------------- 1 file changed, 58 insertions(+), 79 deletions(-) diff --git a/zip.hpp b/zip.hpp index 08d2ec1a..d5066b7a 100644 --- a/zip.hpp +++ b/zip.hpp @@ -6,9 +6,14 @@ #include #include #include +#include namespace iter { + + template + void absorb(Ts&&...) { } + template class Zipped; @@ -16,114 +21,88 @@ namespace iter { Zipped zip(Containers&&...); // specialization for at least 1 template argument - template - class Zipped { - static_assert(!std::is_rvalue_reference::value, - "Itertools cannot be templated with rvalue references"); - - friend Zipped zip( - Container&&, RestContainers&&...); - - template - friend class Zipped; - + template + class Zipped { private: - Container container; - Zipped rest_zipped; - Zipped(Container container, RestContainers&&... rest) - : container(std::forward(container)), - rest_zipped{std::forward(rest)...} + std::tuple containers; + std::make_index_sequence indices; + + public: + Zipped(Containers... in_containers) + : containers{std::forward(in_containers)...} { } - public: class Iterator { private: - using RestIter = - typename Zipped::Iterator; + std::tuple...> iters; + std::make_index_sequence indices; + + template + bool not_equal(const Iterator& other, + std::index_sequence) const { + if (sizeof...(Is) == 0) { + // empty zip() case, return false right away + return false; + } + bool results[] = { true, + (std::get(this->iters) != + std::get(other.iters))... + }; + return std::all_of( + std::begin(results), std::end(results), + [](bool b){ return b; } ); + } + + template + void increment(std::index_sequence) { + absorb(++std::get(this->iters)...); + } + + template + auto deref(std::index_sequence) { + return std::tuple...>{ + (*std::get(this->iters))...}; + } - iterator_type iter; - RestIter rest_iter; public: - constexpr static const bool is_base_iter = false; - Iterator(iterator_type it, const RestIter& rest) - : iter{it}, - rest_iter{rest} + Iterator(iterator_type... its) + : iters{its...} { } Iterator& operator++() { - ++this->iter; - ++this->rest_iter; + this->increment(this->indices); return *this; } bool operator!=(const Iterator& other) const { - return this->iter != other.iter && - (RestIter::is_base_iter || - this->rest_iter != other.rest_iter); + return this->not_equal(other, this->indices); } - auto operator*() -> - decltype(std::tuple_cat( - std::tuple>{ - *this->iter}, - *this->rest_iter)) - { - return std::tuple_cat( - std::tuple>{ - *this->iter}, - *this->rest_iter); + auto operator*() { + return this->deref(this->indices); } }; - - Iterator begin() { - return {std::begin(this->container), - std::begin(this->rest_zipped)}; + private: + template + Iterator make_begin(std::index_sequence) { + return {std::begin(std::get(this->containers))...}; } - Iterator end() { - return {std::end(this->container), - std::end(this->rest_zipped)}; + template + Iterator make_end(std::index_sequence) { + return {std::end(std::get(this->containers))...}; } - }; - - template <> - class Zipped<> { public: - class Iterator { - public: - constexpr static const bool is_base_iter = true; - - Iterator() { } - Iterator(const Iterator&) { } - Iterator& operator=(const Iterator&) { return *this; } - - Iterator& operator++() { - return *this; - } - - // if this were to return true, there would be no need - // for the is_base_iter static class attribute. - // However, returning false causes an empty zip() call - // to reach the "end" immediately. Returning true here - // instead results in an infinite loop in the zip() case - bool operator!=(const Iterator&) const { - return false; - } - - std::tuple<> operator*() { - return std::tuple<>{}; - } - }; Iterator begin() { - return {}; + return this->make_begin(this->indices); } Iterator end() { - return {}; + return this->make_end(this->indices); } - }; + }; template Zipped zip(Containers&&... containers) { From 528836d57f2485b2857e18ba75cf449e40cdb34b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 28 Sep 2014 22:20:06 -0400 Subject: [PATCH 003/596] replaces empty zip if check with overload --- zip.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/zip.hpp b/zip.hpp index d5066b7a..1a449dac 100644 --- a/zip.hpp +++ b/zip.hpp @@ -37,13 +37,14 @@ namespace iter { std::tuple...> iters; std::make_index_sequence indices; + bool not_equal( + const Iterator&, std::index_sequence<>) const { + return false; + } + template bool not_equal(const Iterator& other, std::index_sequence) const { - if (sizeof...(Is) == 0) { - // empty zip() case, return false right away - return false; - } bool results[] = { true, (std::get(this->iters) != std::get(other.iters))... From f7b5c3028321bd73338c525b6312b2d61614d1cc Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 29 Sep 2014 00:32:57 -0400 Subject: [PATCH 004/596] Simplifies by templating on tuple and Is rather than repeating the deduction all over the place. --- zip.hpp | 103 +++++++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/zip.hpp b/zip.hpp index 1a449dac..cc8c58ab 100644 --- a/zip.hpp +++ b/zip.hpp @@ -8,106 +8,93 @@ #include #include - namespace iter { template void absorb(Ts&&...) { } +#if 0 template class Zipped; template Zipped zip(Containers&&...); +#endif // specialization for at least 1 template argument - template + template class Zipped { private: - std::tuple containers; - std::make_index_sequence indices; - + TupType containers; + using iters_tuple = + std::tuple(std::declval()))>...>; public: - Zipped(Containers... in_containers) - : containers{std::forward(in_containers)...} + Zipped(TupType&& in_containers) + : containers(std::move(in_containers)) { } class Iterator { private: - std::tuple...> iters; - std::make_index_sequence indices; + using iters_tuple = + std::tuple(std::declval()))>...>; + using iters_deref_tuple = + std::tuple(std::declval()))>...>; - bool not_equal( - const Iterator&, std::index_sequence<>) const { - return false; - } - - template - bool not_equal(const Iterator& other, - std::index_sequence) const { - bool results[] = { true, - (std::get(this->iters) != - std::get(other.iters))... - }; - return std::all_of( - std::begin(results), std::end(results), - [](bool b){ return b; } ); - } - - template - void increment(std::index_sequence) { - absorb(++std::get(this->iters)...); - } - - template - auto deref(std::index_sequence) { - return std::tuple...>{ - (*std::get(this->iters))...}; - } + iters_tuple iters; public: - Iterator(iterator_type... its) - : iters{its...} + Iterator(iters_tuple&& its) + : iters(std::move(its)) { } Iterator& operator++() { - this->increment(this->indices); + absorb(++std::get(this->iters)...); return *this; } bool operator!=(const Iterator& other) const { - return this->not_equal(other, this->indices); + if (sizeof...(Is) == 0) return false; + + bool results[] = { true, + (std::get(this->iters) != + std::get(other.iters))... + }; + return std::all_of( + std::begin(results), std::end(results), + [](bool b){ return b; } ); } auto operator*() { - return this->deref(this->indices); + return iters_deref_tuple{ + (*std::get(this->iters))...}; } }; - private: - template - Iterator make_begin(std::index_sequence) { - return {std::begin(std::get(this->containers))...}; - } - - template - Iterator make_end(std::index_sequence) { - return {std::end(std::get(this->containers))...}; - } - - public: Iterator begin() { - return this->make_begin(this->indices); + return iters_tuple{ + std::begin(std::get(this->containers))...}; } Iterator end() { - return this->make_end(this->indices); + return iters_tuple{ + std::end(std::get(this->containers))...}; } - }; + }; + + template + Zipped zip_impl( + TupType&& in_containers, std::index_sequence) { + return {std::move(in_containers)}; + } template - Zipped zip(Containers&&... containers) { - return {std::forward(containers)...}; + auto zip(Containers&&... containers) { + return zip_impl(std::tuple{ + std::forward(containers)...}, + std::index_sequence_for{}); } } From 77fc126990b5b7bcebab9009103990c6f3938a7b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 29 Sep 2014 20:42:00 -0400 Subject: [PATCH 005/596] makes Zipped constructor private again --- zip.hpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/zip.hpp b/zip.hpp index cc8c58ab..fb49ecac 100644 --- a/zip.hpp +++ b/zip.hpp @@ -13,36 +13,35 @@ namespace iter { template void absorb(Ts&&...) { } -#if 0 - template + template class Zipped; - template - Zipped zip(Containers&&...); -#endif + template + Zipped zip_impl(TupleType&&, std::index_sequence); - // specialization for at least 1 template argument - template + template class Zipped { private: - TupType containers; + TupleType containers; using iters_tuple = std::tuple(std::declval()))>...>; - public: - Zipped(TupType&& in_containers) + std::get(std::declval()))>...>; + friend Zipped zip_impl( + TupleType&&, std::index_sequence); + + Zipped(TupleType&& in_containers) : containers(std::move(in_containers)) { } + public: class Iterator { private: using iters_tuple = std::tuple(std::declval()))>...>; + std::get(std::declval()))>...>; using iters_deref_tuple = std::tuple(std::declval()))>...>; - + std::get(std::declval()))>...>; iters_tuple iters; public: @@ -84,9 +83,9 @@ namespace iter { } }; - template - Zipped zip_impl( - TupType&& in_containers, std::index_sequence) { + template + Zipped zip_impl( + TupleType&& in_containers, std::index_sequence) { return {std::move(in_containers)}; } From dee21e2f69b5713246d86159284312d50d8fb119 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 29 Sep 2014 21:16:15 -0400 Subject: [PATCH 006/596] refactors type aliases --- iterbase.hpp | 34 ++++++++++++++++++++++++++++++++++ zip.hpp | 26 +++++++------------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 15f0a0a0..63bd142c 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -9,6 +9,7 @@ // this file directly. #include +#include #include #include #include @@ -79,6 +80,39 @@ namespace iter { typename std::remove_const< iterator_deref>::type>::type; + + namespace detail { + template + std::tuple...> iterator_tuple_type_helper( + const std::tuple&); + } + // Given a tuple template argument, evaluates to a tuple of iterators + // for the template argument's contained types. + template + using iterator_tuple_type = + decltype(detail::iterator_tuple_type_helper( + std::declval())); + + namespace detail { + template + std::tuple...> iterator_tuple_deref_helper( + const std::tuple&); + } + + // Given a tuple template argument, evaluates to a tuple of + // what the iterators for the template argument's contained types + // dereference to + template + using iterator_deref_tuple = + decltype(detail::iterator_tuple_deref_helper( + std::declval())); + + // function absorbing all arguments passed to it. used when + // applying a function to a parameter pack but not passing the evaluated + // results anywhere + template + void absorb(Ts&&...) { } + } #endif // #ifndef ITERBASE_HPP_ diff --git a/zip.hpp b/zip.hpp index fb49ecac..f8622553 100644 --- a/zip.hpp +++ b/zip.hpp @@ -10,9 +10,6 @@ namespace iter { - template - void absorb(Ts&&...) { } - template class Zipped; @@ -23,9 +20,6 @@ namespace iter { class Zipped { private: TupleType containers; - using iters_tuple = - std::tuple(std::declval()))>...>; friend Zipped zip_impl( TupleType&&, std::index_sequence); @@ -36,16 +30,10 @@ namespace iter { class Iterator { private: - using iters_tuple = - std::tuple(std::declval()))>...>; - using iters_deref_tuple = - std::tuple(std::declval()))>...>; - iters_tuple iters; + iterator_tuple_type iters; public: - Iterator(iters_tuple&& its) + Iterator(iterator_tuple_type&& its) : iters(std::move(its)) { } @@ -67,19 +55,19 @@ namespace iter { } auto operator*() { - return iters_deref_tuple{ + return iterator_deref_tuple{ (*std::get(this->iters))...}; } }; Iterator begin() { - return iters_tuple{ - std::begin(std::get(this->containers))...}; + return {iterator_tuple_type{ + std::begin(std::get(this->containers))...}}; } Iterator end() { - return iters_tuple{ - std::end(std::get(this->containers))...}; + return {iterator_tuple_type{ + std::end(std::get(this->containers))...}}; } }; From dc7fcd67a40cc9b6ec2464175b8d24ecdb946f97 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 29 Sep 2014 21:21:21 -0400 Subject: [PATCH 007/596] removes mutable (idk why it was ever there) --- imap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.hpp b/imap.hpp index 74e316a7..2418b149 100644 --- a/imap.hpp +++ b/imap.hpp @@ -94,7 +94,7 @@ namespace iter { class Iterator { private: MapFunc map_func; - mutable ZippedIterType zipiter; + ZippedIterType zipiter; public: Iterator(MapFunc map_func, ZippedIterType zipiter) : From 034681307b09c4dd74282dd8428378dbdc2c3f89 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 29 Sep 2014 23:12:05 -0400 Subject: [PATCH 008/596] Cuts down unique_justseen with a lambda This was my original intention, but since lambdas can't appear in an unevaluated context, it didn't work with a trailing return type. With an inferred return type, however, it's fine. --- unique_justseen.hpp | 48 ++++++++++++--------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/unique_justseen.hpp b/unique_justseen.hpp index eaf81747..366e747e 100644 --- a/unique_justseen.hpp +++ b/unique_justseen.hpp @@ -1,7 +1,6 @@ -#ifndef UNIQUE_JUSTSEEN_HPP -#define UNIQUE_JUSTSEEN_HPP +#ifndef ITER_UNIQUE_JUSTSEEN_H_ +#define ITER_UNIQUE_JUSTSEEN_H_ -#include "iterbase.hpp" #include "groupby.hpp" #include "imap.hpp" @@ -9,44 +8,23 @@ #include #include -namespace iter -{ - template - struct GroupFrontGetter{ - auto operator()(iterator_deref&& gb) -> - decltype(*std::begin(gb.second)) { - return *std::begin(gb.second); - } +namespace iter { - auto operator()(iterator_deref& gb) -> - decltype(*std::begin(gb.second)) { - return *std::begin(gb.second); - } - }; - - - // gets first of each group. since each group is decided based on equality - // with the previous item, this results in each item only appearing once template - auto unique_justseen(Container&& container) -> - decltype(imap(GroupFrontGetter(container)))>{}, - groupby(std::forward(container)))) { - return imap(GroupFrontGetter(container)))>{}, + auto unique_justseen(Container&& container) { + // explicit return type in lambda so reference types are preserved + return imap([] (auto&& group) -> iterator_deref { + return *std::begin(group.second); }, groupby(std::forward(container))); } template - auto unique_justseen(std::initializer_list il) -> - decltype(imap(GroupFrontGetter>(il)))>{}, - groupby(std::forward>(il)))) { - return imap(GroupFrontGetter>(il)))>{}, - groupby(std::forward>(il))); + auto unique_justseen(std::initializer_list il) { + return imap( + [](auto&& group) -> iterator_deref> { + return *std::begin(group.second); }, + groupby(il)); } } - -#endif //UNIQUE_JUSTSEEN_HPP +#endif // #ifndef ITER_UNIQUE_JUSTSEEN_H_ From 327db3415b486176f7889ecd630791d54b944979 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 12 Oct 2014 19:41:08 -0400 Subject: [PATCH 009/596] Replaces complex call_with_tuple With std::get and an integer_sequence --- imap.hpp | 61 +++++++++----------------------------------------------- 1 file changed, 9 insertions(+), 52 deletions(-) diff --git a/imap.hpp b/imap.hpp index fd6f0ecc..a88ea5fb 100644 --- a/imap.hpp +++ b/imap.hpp @@ -4,63 +4,23 @@ #include "zip.hpp" #include -#include namespace iter { namespace detail { - - template - struct Expander { - template - static auto call(Functor&& f, Tup&& tup, Ts&&... args) - -> decltype(Expander::call( - std::forward(f), - std::forward(tup), - std::get(tup), - std::forward(args)...)) - { - // recurse - return Expander::call( - std::forward(f), - std::forward(tup), - std::get(tup), // pull out one element - std::forward(args)...); // everything already expanded + template + auto call_with_tuple_impl(MapFunc&& mf, TupleType&& tup, + std::index_sequence) { + return mf(std::get(tup)...); } - }; - template - struct Expander<0, Functor, Tup> { - template - static auto call(Functor&& f, Tup&&, Ts&&... args) - -> decltype(f(std::forward(args)...)) - { - static_assert( - std::tuple_size< - typename std::remove_reference::type>::value - == sizeof...(Ts), - "tuple has not been fully expanded"); - return f(std::forward(args)...); // the actual call + template + auto call_with_tuple(MapFunc&& mf, std::tuple&& tup){ + return call_with_tuple_impl( + mf, tup, std::index_sequence_for{}); } - }; - - template - auto call_with_tuple(Functor&& f, Tup&& tup) - -> decltype(Expander::type>::value, - Functor, Tup>::call( - std::forward(f), - std::forward(tup))) - { - return Expander::type>::value, - Functor, Tup>::call( - std::forward(f), - std::forward(tup)); } - } // end detail - //Forward declarations of IMap and imap template class IMap; @@ -102,10 +62,7 @@ namespace iter { zipiter(zipiter) { } - auto operator*() -> - decltype(detail::call_with_tuple( - this->map_func, *(this->zipiter))) - { + auto operator*() { return detail::call_with_tuple( this->map_func, *(this->zipiter)); } From 2f3df24376ce6304d92ba46ce98674052f6971b1 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 15 Oct 2014 10:29:30 -0400 Subject: [PATCH 010/596] Moves call_with_tuple into iterbase and makes it more flexible --- imap.hpp | 16 +--------------- iterbase.hpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/imap.hpp b/imap.hpp index a88ea5fb..38d7241a 100644 --- a/imap.hpp +++ b/imap.hpp @@ -7,20 +7,6 @@ namespace iter { - namespace detail { - template - auto call_with_tuple_impl(MapFunc&& mf, TupleType&& tup, - std::index_sequence) { - return mf(std::get(tup)...); - } - - template - auto call_with_tuple(MapFunc&& mf, std::tuple&& tup){ - return call_with_tuple_impl( - mf, tup, std::index_sequence_for{}); - } - } - //Forward declarations of IMap and imap template class IMap; @@ -63,7 +49,7 @@ namespace iter { { } auto operator*() { - return detail::call_with_tuple( + return call_with_tuple( this->map_func, *(this->zipiter)); } diff --git a/iterbase.hpp b/iterbase.hpp index 63bd142c..da6e703e 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -107,12 +107,33 @@ namespace iter { decltype(detail::iterator_tuple_deref_helper( std::declval())); + // ---- Tuple utilities ---- // + // function absorbing all arguments passed to it. used when // applying a function to a parameter pack but not passing the evaluated // results anywhere template void absorb(Ts&&...) { } + namespace detail { + template + auto call_with_tuple_impl(Func&& mf, TupleType&& tup, + std::index_sequence) { + return mf(std::get(tup)...); + } + } + + // expand a TupleType into individual arguments when calling a Func + template + auto call_with_tuple(Func&& mf, TupleType&& tup) { + constexpr auto TUP_SIZE = std::tuple_size< + typename std::remove_reference::type>::value; + return detail::call_with_tuple_impl( + std::forward(mf), + std::forward(tup), + std::make_index_sequence{}); + } + } #endif // #ifndef ITERBASE_HPP_ From e23c73d54fe75e78dafb300fdefd4fa5f97a63f0 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 17 Oct 2014 14:12:29 -0400 Subject: [PATCH 011/596] describes purpose of c++14 branch --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d44c246..81cd774c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ -CPPItertools +CPPItertools C++14 development Branch ============ +**NOTE**: this branch is for refining and moving forward with the C++14 +standard. It will be merged into master when compiler and library +support for the standard approaches completion in common compilers. +Specifically I'm considering clang and gcc, along with libstdc++ +and libc++ + range-based for loop add-ons inspired by the Python builtins and itertools library. Like itertools and the Python3 builtins, this library uses lazy evaluation wherever possible. From f3e78488bc30b0fe763d0e1a135d09d1b221e498 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 18 Oct 2014 15:10:43 -0400 Subject: [PATCH 012/596] relaced decay with decay_t --- iterbase.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index da6e703e..d0eade82 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -117,7 +117,7 @@ namespace iter { namespace detail { template - auto call_with_tuple_impl(Func&& mf, TupleType&& tup, + decltype(auto) call_with_tuple_impl(Func&& mf, TupleType&& tup, std::index_sequence) { return mf(std::get(tup)...); } @@ -125,9 +125,9 @@ namespace iter { // expand a TupleType into individual arguments when calling a Func template - auto call_with_tuple(Func&& mf, TupleType&& tup) { + decltype(auto) call_with_tuple(Func&& mf, TupleType&& tup) { constexpr auto TUP_SIZE = std::tuple_size< - typename std::remove_reference::type>::value; + std::decay_t>::value; return detail::call_with_tuple_impl( std::forward(mf), std::forward(tup), From 26755551c32b956cfa40811199fbe6eee5853348 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 18 Oct 2014 17:35:09 -0400 Subject: [PATCH 013/596] marks operator* as decltype(auto) in imap iterator --- imap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imap.hpp b/imap.hpp index 38d7241a..e39a468c 100644 --- a/imap.hpp +++ b/imap.hpp @@ -48,7 +48,7 @@ namespace iter { zipiter(zipiter) { } - auto operator*() { + decltype(auto) operator*() { return call_with_tuple( this->map_func, *(this->zipiter)); } From c250beb3a3a63335ceedfe2b1c9e8592e80ea48b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 18 Oct 2014 20:09:54 -0400 Subject: [PATCH 014/596] adds test for starmap --- tests/teststarmap.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/teststarmap.cpp diff --git a/tests/teststarmap.cpp b/tests/teststarmap.cpp new file mode 100644 index 00000000..0d293abc --- /dev/null +++ b/tests/teststarmap.cpp @@ -0,0 +1,75 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using iter::starmap; + +double f(double d, int i) { + return d * i; +} + +std::string g(const std::string& s, int i, double d) { + std::stringstream ss; + ss << s << ' ' << i << ' ' << d; + return ss.str(); +} + +void test_normal() { + std::cout << "vector>\n"; + std::vector> v1 = {{1.0, 2}, {3.2, 42}, {6.9, 7}}; + for (auto&& i : starmap(f, v1)) { + std::cout << i << '\n'; + } + std::cout << '\n'; + + std::cout << "list\n"; + { + using T = std::tuple; + std::list li = + {T{"hey", 42, 6.9}, T{"there", 3, 4.0}, T{"yall", 5, 3.1}}; + for (auto&& s : starmap(g, li)) { + std::cout << s << '\n'; + } + } + std::cout << '\n'; +} + +struct Callable { + int operator()(int a, int b, int c) { + return a + b + c; + } + + int operator()(int a) { + return a; + } +}; + +void test_tuple_of_tuples() { + auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); + Callable c; + std::cout << "tuple, tuple>\n"; + for (auto&& i : starmap(c, tup)) { + std::cout << i << '\n'; + } + + auto tup2 = std::make_tuple(std::array{15, 100, 2000}, + std::make_tuple(16)); + std::cout << "tuple, tuple>\n"; + for (auto&& i : starmap(c, tup2)) { + std::cout << i << '\n'; + } + std::cout << '\n'; +} + +int main() { + test_normal(); + test_tuple_of_tuples(); + +} From adbf9ece561b3b7ab60501255080c4c20b71a50e Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 18 Oct 2014 20:10:21 -0400 Subject: [PATCH 015/596] adds starmap --- starmap.hpp | 160 +++++++++++++++++++++++++++++++++++++++++++++++ tests/.gitignore | 1 + tests/SConstruct | 1 + 3 files changed, 162 insertions(+) create mode 100644 starmap.hpp diff --git a/starmap.hpp b/starmap.hpp new file mode 100644 index 00000000..165cc363 --- /dev/null +++ b/starmap.hpp @@ -0,0 +1,160 @@ +#ifndef ITER_STARMAP_H_ +#define ITER_STARMAP_H_ + +#include "iterbase.hpp" + +#include +#include + +namespace iter { + template + class StarMapper { + private: + Func func; + Container container; + public: + StarMapper(Func f, Container c) + : func(f), + container(std::forward(c)) + { } + + class Iterator { + private: + Func func; + iterator_type sub_iter; + public: + Iterator(Func f, iterator_type iter) + : func(f), + sub_iter(iter) + { } + + bool operator!=(const Iterator& other) const { + return this->sub_iter != other.sub_iter; + } + + Iterator operator++() { + ++this->sub_iter; + return *this; + } + + decltype(auto) operator*() { + return call_with_tuple(this->func, *this->sub_iter); + } + }; + + Iterator begin() { + return {this->func, std::begin(this->container)}; + } + + Iterator end() { + return {this->func, std::end(this->container)}; + } + }; + + template + StarMapper starmap(Func func, Container&& container) { + return {func, std::forward(container)}; + } + + template >::value> + class TupleStarMapper { + private: + Func func; + TupleType tup; + public: + TupleStarMapper(Func f, TupleType t) + : func(f), + tup(std::forward(t)) + { } + + template + class Iterator { + private: + Func func; + TupleType& tup; + bool passed; + Iterator<0, Idx + 1> next_level; + + public: + Iterator(Func f, TupleType& t, bool done) + : func(f), + tup(t), + passed{done}, + next_level(f, t, done) + { } + + decltype(auto) operator*() { + if (this->passed) { + return *this->next_level; + } else { + return call_with_tuple( + this->func, std::get(this->tup)); + } + } + + Iterator operator++() { + if (!this->passed) { + this->passed = true; + } else { + ++this->next_level; + } + return *this; + } + + bool operator!=(const Iterator& other) const { + return this->passed != other.passed + || this->next_level != other.next_level; + } + }; + + template + class Iterator { + private: + // data members unused since this should never get + // dereferenced, but are needed to compile + Func func; + TupleType& tup; + public: + Iterator(Func f, TupleType& t, bool) + : func(f), + tup(t) + { } + + decltype(auto) operator*() { + assert(false && "deref of last level in starmap"); + return call_with_tuple(func, std::get<0>(tup)); + } + + Iterator operator++() { + assert(false && "++ on last level of starmap"); + return *this; + } + + bool operator!=(const Iterator&) const { + return false; + } + }; + + Iterator<0, 0> begin() { + return {this->func, this->tup, false}; + } + + Iterator<0, 0> end() { + return {this->func, this->tup, true}; + } + }; + + template + TupleStarMapper> starmap( + Func func, std::tuple tup) { + return {func, tup}; + } + + +} + + + + +#endif // #ifndef ITER_STARMAP_H_ diff --git a/tests/.gitignore b/tests/.gitignore index 7daa7f9d..a72824de 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -28,6 +28,7 @@ testgrouper testcommand_chains testgroupby testsorted +teststarmap testunique_justseen testunique_everseen .sconsign.dblite diff --git a/tests/SConstruct b/tests/SConstruct index 7a4abeec..d1271d7d 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -34,6 +34,7 @@ progs = Split(''' powerset sliding_window imap + starmap count filterfalse grouper From ba4c3b940664855ebbcf4aea64cc3043d375a2c2 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 18 Oct 2014 20:10:58 -0400 Subject: [PATCH 016/596] adds starmap to itertools.hpp --- itertools.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/itertools.hpp b/itertools.hpp index 55039902..3ef9dd1e 100644 --- a/itertools.hpp +++ b/itertools.hpp @@ -1,5 +1,5 @@ -#ifndef ITERTOOLS_HPP -#define ITERTOOLS_HPP +#ifndef ITERTOOLS_HPP_ +#define ITERTOOLS_HPP_ #include "accumulate.hpp" #include "chain.hpp" @@ -24,6 +24,7 @@ #include "reversed.hpp" #include "slice.hpp" #include "sorted.hpp" +#include "starmap.hpp" #include "takewhile.hpp" #include "unique_everseen.hpp" #include "unique_justseen.hpp" From bc9b13799fc96452f7a5fcaef3181cef97f29a9c Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 19 Oct 2014 12:32:22 -0400 Subject: [PATCH 017/596] Replaces recursive iterators with flat array Because TupleStarMapper::Iterator::operator* causes a recursive call, it gets slower as one goes further along, the cost of longer tuples is unexpectedly high. This new scheme uses a set of classes templated on the index they use in std::get, all inheriting from a common base. An array of base class pointers can then be indexed into. It incurs a virtual function call but that's worth it. The dynamic allocation seems to be the bigger cost, but it's possible that can be alleviated as well. --- starmap.hpp | 123 +++++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 165cc363..14f14108 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -4,9 +4,13 @@ #include "iterbase.hpp" #include +#include +#include #include +#include namespace iter { + // starmap with a container where T is one of tuple, pair, array template class StarMapper { private: @@ -56,101 +60,104 @@ namespace iter { return {func, std::forward(container)}; } + + // starmap for a tuple or pair of tuples or pairs template >::value> class TupleStarMapper { private: - Func func; - TupleType tup; - public: - TupleStarMapper(Func f, TupleType t) - : func(f), - tup(std::forward(t)) - { } + class TupleExpanderBase { + protected: + // deduced return type to return of Func when called with + // one of TupleType + using ResultType = + decltype(call_with_tuple( + std::declval(), + std::get<0>(std::declval()))); + public: + virtual ResultType call() = 0; - template - class Iterator { + virtual ~TupleExpanderBase() { } + }; + + template + class TupleExpander : public TupleExpanderBase { private: Func func; TupleType& tup; - bool passed; - Iterator<0, Idx + 1> next_level; - public: - Iterator(Func f, TupleType& t, bool done) + TupleExpander(Func f, TupleType& t) : func(f), - tup(t), - passed{done}, - next_level(f, t, done) + tup(t) { } - decltype(auto) operator*() { - if (this->passed) { - return *this->next_level; - } else { - return call_with_tuple( - this->func, std::get(this->tup)); - } + typename TupleExpanderBase::ResultType call() override { + return call_with_tuple( + this->func, std::get(this->tup)); } + }; - Iterator operator++() { - if (!this->passed) { - this->passed = true; - } else { - ++this->next_level; - } - return *this; - } + private: + Func func; + TupleType tup; + std::array, Size> tuple_getters; - bool operator!=(const Iterator& other) const { - return this->passed != other.passed - || this->next_level != other.next_level; - } - }; + template + TupleStarMapper(Func f, TupleType t, std::index_sequence) + : func(f), + tup(std::forward(t)), + tuple_getters( + {std::make_unique>(func, tup)...}) + { } + + public: + TupleStarMapper(Func f, TupleType t) + : TupleStarMapper(f, std::forward(t), + std::make_index_sequence{}) + { } - template - class Iterator { + class Iterator { private: - // data members unused since this should never get - // dereferenced, but are needed to compile - Func func; - TupleType& tup; + std::array, Size>& + tuple_getters; + std::size_t index; + public: - Iterator(Func f, TupleType& t, bool) - : func(f), - tup(t) + Iterator(std::array< + std::unique_ptr, Size>& tg, + std::size_t i) + : tuple_getters(tg), + index{i} { } - + decltype(auto) operator*() { - assert(false && "deref of last level in starmap"); - return call_with_tuple(func, std::get<0>(tup)); + return this->tuple_getters[this->index]->call(); } Iterator operator++() { - assert(false && "++ on last level of starmap"); + ++this->index; return *this; } - bool operator!=(const Iterator&) const { - return false; + bool operator!=(const Iterator& other) const { + return this->index != other.index; } }; - Iterator<0, 0> begin() { - return {this->func, this->tup, false}; + Iterator begin() { + return {this->tuple_getters, 0}; } - Iterator<0, 0> end() { - return {this->func, this->tup, true}; + Iterator end() { + return {this->tuple_getters, Size}; } }; template - TupleStarMapper> starmap( - Func func, std::tuple tup) { + TupleStarMapper&> starmap( + Func func, std::tuple& tup) { return {func, tup}; } - } From 917ad43c328e8720d58fe796209fd381e755694e Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 20 Oct 2014 00:07:13 -0400 Subject: [PATCH 018/596] adds starmap test with pair of tuples --- tests/teststarmap.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/teststarmap.cpp b/tests/teststarmap.cpp index 0d293abc..992c7ce3 100644 --- a/tests/teststarmap.cpp +++ b/tests/teststarmap.cpp @@ -66,6 +66,14 @@ void test_tuple_of_tuples() { std::cout << i << '\n'; } std::cout << '\n'; + + std::cout << "pair, tuple>\n"; + auto p = std::make_pair(std::array{15, 100, 2000}, + std::make_tuple(16)); + for (auto&& i : starmap(c, p)) { + std::cout << i << '\n'; + } + std::cout << '\n'; } int main() { From 7350d07421db5c3be58b8563bf9565775da036a3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 20 Oct 2014 00:08:27 -0400 Subject: [PATCH 019/596] supports starmap over a pair --- starmap.hpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 14f14108..920825ec 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -55,12 +55,14 @@ namespace iter { } }; + + template - StarMapper starmap(Func func, Container&& container) { + StarMapper starmap_helper( + Func func, Container&& container, std::false_type) { return {func, std::forward(container)}; } - // starmap for a tuple or pair of tuples or pairs template >::value> @@ -153,12 +155,27 @@ namespace iter { } }; - template - TupleStarMapper&> starmap( - Func func, std::tuple& tup) { - return {func, tup}; + template + TupleStarMapper starmap_helper( + Func func, TupleType&& tup, std::true_type) { + return {func, std::forward(tup)}; } + // "tag dispatch" to differentiate between normal containers and + // tuple-like containers, things that work with std::get + template + struct is_tuple_like : public std::false_type { }; + + template + struct is_tuple_like(std::declval()), void())> + : public std::true_type { }; + + template + auto starmap(Func func, Seq&& sequence) { + return starmap_helper( + func, std::forward(sequence), + is_tuple_like{}); + } } From f9209106698999a3ea0b363054acbf4e30d64876 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 20 Oct 2014 00:11:45 -0400 Subject: [PATCH 020/596] implements imap in terms of starmap and gets rid of nearly the entire imap.hpp in the process --- imap.hpp | 75 +++----------------------------------------------------- 1 file changed, 3 insertions(+), 72 deletions(-) diff --git a/imap.hpp b/imap.hpp index e39a468c..8c5721aa 100644 --- a/imap.hpp +++ b/imap.hpp @@ -2,84 +2,15 @@ #define ITER_IMAP_H_ #include "zip.hpp" +#include "starmap.hpp" #include namespace iter { - - //Forward declarations of IMap and imap - template - class IMap; - - template - IMap imap(MapFunc, Containers&&...); - - template - class IMap { - // The imap function is the only thing allowed to create a IMap - friend IMap imap(MapFunc, Containers&& ...); - - using ZippedType = decltype(zip(std::declval()...)); - using ZippedIterType = iterator_type; - private: - MapFunc map_func; - ZippedType zipped; - - // Value constructor for use only in the imap function - IMap(MapFunc map_func, Containers&& ... containers) : - map_func(map_func), - zipped(zip(std::forward(containers)...)) - { } - IMap() = delete; - IMap& operator=(const IMap&) = delete; - - public: - IMap(const IMap&) = default; - IMap(IMap&&) = default; - - class Iterator { - private: - MapFunc map_func; - ZippedIterType zipiter; - - public: - Iterator(MapFunc map_func, ZippedIterType zipiter) : - map_func(map_func), - zipiter(zipiter) - { } - - decltype(auto) operator*() { - return call_with_tuple( - this->map_func, *(this->zipiter)); - } - - Iterator& operator++() { - ++this->zipiter; - return *this; - } - - bool operator!=(const Iterator& other) const { - return this->zipiter != other.zipiter; - } - }; - - Iterator begin() { - return {this->map_func, this->zipped.begin()}; - } - - Iterator end() { - return {this->map_func, this->zipped.end()}; - } - - }; - - // Helper function to instantiate a IMap template - IMap imap( - MapFunc map_func, Containers&& ... containers) { - return {map_func, std::forward(containers)...}; + auto imap(MapFunc map_func, Containers&& ... containers) { + return starmap(map_func, zip(std::forward(containers)...)); } - } #endif // #ifndef ITER_IMAP_H_ From c413262eea9329ed534062f7f83ec54459daa3dc Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 23 Oct 2014 11:13:49 -0400 Subject: [PATCH 021/596] Adds braces around array initliazation --- starmap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starmap.hpp b/starmap.hpp index 920825ec..dadc5884 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -109,7 +109,7 @@ namespace iter { : func(f), tup(std::forward(t)), tuple_getters( - {std::make_unique>(func, tup)...}) + {{std::make_unique>(func, tup)...}}) { } public: From 0d6811c0a1deeb2329830f6bd1efd47f674d8c38 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 23 Oct 2014 11:14:07 -0400 Subject: [PATCH 022/596] Adds braces around array initializations --- tests/teststarmap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/teststarmap.cpp b/tests/teststarmap.cpp index 992c7ce3..f85bd40d 100644 --- a/tests/teststarmap.cpp +++ b/tests/teststarmap.cpp @@ -59,7 +59,7 @@ void test_tuple_of_tuples() { std::cout << i << '\n'; } - auto tup2 = std::make_tuple(std::array{15, 100, 2000}, + auto tup2 = std::make_tuple(std::array{{15, 100, 2000}}, std::make_tuple(16)); std::cout << "tuple, tuple>\n"; for (auto&& i : starmap(c, tup2)) { @@ -68,7 +68,7 @@ void test_tuple_of_tuples() { std::cout << '\n'; std::cout << "pair, tuple>\n"; - auto p = std::make_pair(std::array{15, 100, 2000}, + auto p = std::make_pair(std::array{{15, 100, 2000}}, std::make_tuple(16)); for (auto&& i : starmap(c, p)) { std::cout << i << '\n'; From 6dc80a1ef247f0cb78206b50822e75de0ae893fa Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 23 Oct 2014 11:16:12 -0400 Subject: [PATCH 023/596] makes absorb() non-templated --- iterbase.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index d0eade82..c60713df 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -112,8 +112,7 @@ namespace iter { // function absorbing all arguments passed to it. used when // applying a function to a parameter pack but not passing the evaluated // results anywhere - template - void absorb(Ts&&...) { } + void absorb(...) { } namespace detail { template From 0ce44f35f578feef8536ac5829cf65969c9e80b9 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 24 Oct 2014 10:53:17 -0400 Subject: [PATCH 024/596] uses anonymous template parm in is_tuple_like --- starmap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starmap.hpp b/starmap.hpp index 920825ec..34b91737 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -163,7 +163,7 @@ namespace iter { // "tag dispatch" to differentiate between normal containers and // tuple-like containers, things that work with std::get - template + template struct is_tuple_like : public std::false_type { }; template From 5fe7c0f381d5e1d1fcd7e4f16f1a7fe772404873 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Tue, 28 Oct 2014 16:36:15 -0400 Subject: [PATCH 025/596] Flattens chain Chain is flattened using a similar approach to starmap. A different instantiation of each ChainIterWrapper for each index. This avoids having a nested class structure, and the time to perform operator* doesn't increase as one gets further into the chain. An index keeps track of which iterator we're on each step of the way. It's not very pretty though. --- chain.hpp | 182 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 102 insertions(+), 80 deletions(-) diff --git a/chain.hpp b/chain.hpp index e5df892d..0c75c4c5 100644 --- a/chain.hpp +++ b/chain.hpp @@ -8,128 +8,140 @@ #include #include #include +#include +#include namespace iter { // rather than a chain function, use a callable object to support // from_iterable class ChainMaker; - template + template class Chained { friend class ChainMaker; - template - friend class Chained; private: - Container container; - Chained rest_chained; - Chained(Container container, RestContainers&&... rest) - : container(std::forward(container)), - rest_chained{std::forward(rest)...} - { } + class ChainIterWrapperBase { + protected: + using ResultType = + iterator_deref>; + public: + virtual ~ChainIterWrapperBase() { } + virtual bool operator!=( + const ChainIterWrapperBase&) const = 0; + virtual bool operator==( + const ChainIterWrapperBase&) const = 0; + virtual ResultType operator*() = 0; + virtual ChainIterWrapperBase& operator++() = 0; + }; - public: - class Iterator { + template + class ChainIterWrapper : public ChainIterWrapperBase { private: - using RestIter = - typename Chained::Iterator; iterator_type sub_iter; - const iterator_type sub_end; - RestIter rest_iter; - bool at_end; public: - Iterator(const iterator_type& s_begin, - const iterator_type& s_end, - RestIter rest_iter) - : sub_iter{s_begin}, - sub_end{s_end}, - rest_iter{rest_iter}, - at_end{!(sub_iter != sub_end)} + ChainIterWrapper(const iterator_type& iter) + : sub_iter{iter} { } - - Iterator& operator++() { - if (this->at_end) { - ++this->rest_iter; - } else { - ++this->sub_iter; - if (!(this->sub_iter != this->sub_end)) { - this->at_end = true; - } - } - return *this; + + bool operator!=(const ChainIterWrapperBase& other) + const override { + return this->sub_iter != + static_cast( + other).sub_iter; } - bool operator!=(const Iterator& other) const { - return this->sub_iter != other.sub_iter || - this->rest_iter != other.rest_iter; + bool operator==(const ChainIterWrapperBase& other) + const override { + return !(*this != + static_cast(other)); } - iterator_deref operator*() { - return this->at_end ? - *this->rest_iter : *this->sub_iter; + typename ChainIterWrapper::ResultType operator*() { + return *this->sub_iter; } - }; - Iterator begin() { - return {std::begin(this->container), - std::end(this->container), - std::begin(this->rest_chained)}; - } + ChainIterWrapper& operator++() override { + ++this->sub_iter; + return *this; + } + }; - Iterator end() { - return {std::end(this->container), - std::end(this->container), - std::end(this->rest_chained)}; - } - }; - template - class Chained { - friend class ChainMaker; - template - friend class Chained; private: - Container container; - Chained(Container container) - : container(std::forward(container)) + using ArrayType = + std::array, + sizeof...(Is)>; + TupleType containers; + ArrayType end_iter_wrappers; + + Chained(TupleType&& tup_containers) + : containers(std::move(tup_containers)), + end_iter_wrappers{{std::make_unique< + ChainIterWrapper>>( + std::end(std::get(this->containers)))...}} { } public: class Iterator { private: - iterator_type sub_iter; - const iterator_type sub_end; + using ArrayType = + std::array, + sizeof...(Is)>; + + ArrayType iter_wrappers; + const ArrayType& end_iter_wrappers; + std::size_t index; + + void check_index() { + while (this->index < iter_wrappers.size() + && *this->iter_wrappers[this->index] + == *this->end_iter_wrappers[this->index]) { + ++this->index; + } + } + public: - Iterator(const iterator_type& s_begin, - const iterator_type& s_end) - : sub_iter{s_begin}, - sub_end{s_end} - { } - + Iterator(ArrayType&& iters, ArrayType& ends, std::size_t i) + : iter_wrappers(std::move(iters)), + end_iter_wrappers(ends), + index{i} + { + this->check_index(); + } + Iterator& operator++() { - ++this->sub_iter; + ++*this->iter_wrappers[this->index]; + this->check_index(); return *this; } - bool operator!=(const Iterator& other) const { - return this->sub_iter != other.sub_iter; + decltype(auto) operator*() { + return **this->iter_wrappers[this->index]; } - iterator_deref operator*() { - return *this->sub_iter; + bool operator!=(const Iterator& other) const { + return this->index != other.index; } }; + Iterator begin() { - return {std::begin(this->container), - std::end(this->container)}; + ArrayType a{{ + std::make_unique< + ChainIterWrapper>>( + std::begin(std::get(this->containers)) + )...}}; + return {std::move(a), end_iter_wrappers, 0}; } Iterator end() { - return {std::end(this->container), - std::end(this->container)}; + ArrayType a{{std::unique_ptr< + ChainIterWrapper>>{ + nullptr}...}}; + return {std::move(a), end_iter_wrappers, sizeof...(Is)}; } }; @@ -179,7 +191,6 @@ namespace iter { } return *this; } - bool operator!=(const Iterator& other) const { return this->top_level_iter != other.top_level_iter && @@ -203,11 +214,22 @@ namespace iter { class ChainMaker { + private: + template + Chained chain_impl( + TupleType&& in_containers, + std::index_sequence) const { + return {std::move(in_containers)}; + } + public: // expose regular call operator to provide usual chain() template - Chained operator()(Containers&&... cs) const { - return {std::forward(cs)...}; + auto operator()(Containers&&... cs) const { + return this->chain_impl( + std::tuple{ + std::forward(cs)...}, + std::index_sequence_for{}); } // chain.from_iterable From 0305423f4079880456fc66a0d78d538bcaaac6a3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 9 Nov 2014 23:46:20 -0500 Subject: [PATCH 026/596] adds chain iterator copy ctor --- chain.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/chain.hpp b/chain.hpp index d116fcd4..70e1b2f7 100644 --- a/chain.hpp +++ b/chain.hpp @@ -106,12 +106,21 @@ namespace iter { public: Iterator(ArrayType&& iters, ArrayType& ends, std::size_t i) : iter_wrappers(std::move(iters)), - end_iter_wrappers(ends), + end_iter_wrappers{ends}, index{i} { this->check_index(); } + Iterator(const Iterator& other) + : iter_wrappers{{ + // make this not so awful. + std::unique_ptr{new ChainIterWrapper>(dynamic_cast>&>(*std::get(other.iter_wrappers)))}... + }}, + end_iter_wrappers{other.end_iter_wrappers}, + index{other.index} + { } + Iterator& operator++() { ++*this->iter_wrappers[this->index]; this->check_index(); From 300caf936f7ded86b6a3d5579c1942e7dfbee60d Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Tue, 11 Nov 2014 23:55:01 -0500 Subject: [PATCH 027/596] Replaces polymorphic solution with std::functions ..which are also polymorphic, but it allows for a single const static array per instatiation of TupleStarMapper --- iterbase.hpp | 4 ++ starmap.hpp | 115 +++++++++++++++++++++++++-------------------------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index d0eade82..5564bcb8 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -134,6 +134,10 @@ namespace iter { std::make_index_sequence{}); } + // this will eventually make it into the standard, but for now: + template + using void_t = void; + } #endif // #ifndef ITERBASE_HPP_ diff --git a/starmap.hpp b/starmap.hpp index 34b91737..272753e6 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -59,81 +59,56 @@ namespace iter { template StarMapper starmap_helper( - Func func, Container&& container, std::false_type) { - return {func, std::forward(container)}; + Func&& func, Container&& container, std::false_type) { + return {std::forward(func), std::forward(container)}; } // starmap for a tuple or pair of tuples or pairs - template >::value> + template class TupleStarMapper { private: - class TupleExpanderBase { - protected: - // deduced return type to return of Func when called with - // one of TupleType - using ResultType = - decltype(call_with_tuple( - std::declval(), - std::get<0>(std::declval()))); - public: - virtual ResultType call() = 0; + Func func; + TupType tup; - virtual ~TupleExpanderBase() { } - }; + private: + static_assert(sizeof...(Is) + == std::tuple_size>::value, + "tuple size doesn't match size of Is"); template - class TupleExpander : public TupleExpanderBase { - private: - Func func; - TupleType& tup; - public: - TupleExpander(Func f, TupleType& t) - : func(f), - tup(t) - { } + static decltype(auto) get_and_call_with_tuple(Func& f, TupType &t){ + return call_with_tuple(f, std::get(t)); + } - typename TupleExpanderBase::ResultType call() override { - return call_with_tuple( - this->func, std::get(this->tup)); - } - }; + using v = + void_t(func, tup))...>; - private: - Func func; - TupleType tup; - std::array, Size> tuple_getters; + using ResultType = decltype(get_and_call_with_tuple<0>(func, tup)); + using CallerFunc = std::function; - template - TupleStarMapper(Func f, TupleType t, std::index_sequence) - : func(f), - tup(std::forward(t)), - tuple_getters( - {std::make_unique>(func, tup)...}) - { } + const static std::array callers; public: - TupleStarMapper(Func f, TupleType t) - : TupleStarMapper(f, std::forward(t), - std::make_index_sequence{}) + TupleStarMapper(Func f, TupType t) + : func(std::forward(f)), + tup(std::forward(t)) { } class Iterator { private: - std::array, Size>& - tuple_getters; + Func& func; + TupType& tup; std::size_t index; public: - Iterator(std::array< - std::unique_ptr, Size>& tg, - std::size_t i) - : tuple_getters(tg), + Iterator(Func& f, TupType& t, std::size_t i) + : func{f}, + tup{t}, index{i} { } decltype(auto) operator*() { - return this->tuple_getters[this->index]->call(); + return callers[this->index](this->func, this->tup); } Iterator operator++() { @@ -147,20 +122,41 @@ namespace iter { }; Iterator begin() { - return {this->tuple_getters, 0}; + return {this->func, this->tup, 0}; } Iterator end() { - return {this->tuple_getters, Size}; + return {this->func, this->tup, sizeof...(Is)}; } }; + // initialize array with a caller function for each index + template + const std::array< + typename TupleStarMapper::CallerFunc, + sizeof...(Is)> + TupleStarMapper::callers{{ + get_and_call_with_tuple...}}; - template - TupleStarMapper starmap_helper( - Func func, TupleType&& tup, std::true_type) { - return {func, std::forward(tup)}; + + + template + TupleStarMapper starmap_helper_impl( + Func&& func, TupType&& tup, std::index_sequence) + { + return {std::forward(func), std::forward(tup)}; } + template + auto starmap_helper( + Func&& func, TupType&& tup, std::true_type) { + return starmap_helper_impl( + std::forward(func), + std::forward(tup), + std::make_index_sequence< + std::tuple_size>::value>{}); + } + + // "tag dispatch" to differentiate between normal containers and // tuple-like containers, things that work with std::get template @@ -171,9 +167,10 @@ namespace iter { : public std::true_type { }; template - auto starmap(Func func, Seq&& sequence) { + auto starmap(Func&& func, Seq&& sequence) { return starmap_helper( - func, std::forward(sequence), + std::forward(func), + std::forward(sequence), is_tuple_like{}); } } From 7d878e57fd1521a7ea29bd6f0d6d077d3a61e893 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 12 Nov 2014 00:08:51 -0500 Subject: [PATCH 028/596] Computes callers as constexpr I did it constexpr. I'm pretty happy with this, I can't see it getting much better outside of not writing the code at all. --- iterbase.hpp | 4 ---- starmap.hpp | 14 +++++--------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 5564bcb8..d0eade82 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -134,10 +134,6 @@ namespace iter { std::make_index_sequence{}); } - // this will eventually make it into the standard, but for now: - template - using void_t = void; - } #endif // #ifndef ITERBASE_HPP_ diff --git a/starmap.hpp b/starmap.hpp index 272753e6..4a41cba9 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -80,13 +80,11 @@ namespace iter { return call_with_tuple(f, std::get(t)); } - using v = - void_t(func, tup))...>; - using ResultType = decltype(get_and_call_with_tuple<0>(func, tup)); - using CallerFunc = std::function; + using CallerFunc = ResultType (*)(Func&, TupType&); - const static std::array callers; + constexpr static std::array callers{{ + get_and_call_with_tuple...}}; public: TupleStarMapper(Func f, TupType t) @@ -129,13 +127,11 @@ namespace iter { return {this->func, this->tup, sizeof...(Is)}; } }; - // initialize array with a caller function for each index template - const std::array< + constexpr std::array< typename TupleStarMapper::CallerFunc, sizeof...(Is)> - TupleStarMapper::callers{{ - get_and_call_with_tuple...}}; + TupleStarMapper::callers; From 56b5a6498b9d430d65bb2507be62faa971be9cef Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 12 Nov 2014 21:08:58 -0500 Subject: [PATCH 029/596] adds test for iterator assignment to chain --- tests/testchain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/testchain.cpp b/tests/testchain.cpp index 19ab374d..3dfde3d1 100644 --- a/tests/testchain.cpp +++ b/tests/testchain.cpp @@ -19,6 +19,11 @@ int main() { for (auto e : chain(ivec, lvec)) { std::cout << e << std::endl; } + + auto c = chain(ivec, lvec); + auto it = std::begin(c); + auto it2 = std::begin(c); + it = it2; } { std::vector empty{}; @@ -58,4 +63,5 @@ int main() { std::cout << i << '\n'; } } + } From 3dabc8757c0865cc3824f13534e4356f8a734daf Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 12 Nov 2014 21:10:37 -0500 Subject: [PATCH 030/596] Uses constexpr array of funcion pointers for chain Instead of the polymorphism and the base class, I was able to use a similar approach as in starmap to get chain to act more dynamic than it really is. Starmap needed only one set of function pointers, for the dereferencing, chain is admittedly more complicated because it needs one for each operation that must be performed per iterator. --- chain.hpp | 259 ++++++++++++++++++++++++++---------------------------- 1 file changed, 124 insertions(+), 135 deletions(-) diff --git a/chain.hpp b/chain.hpp index 70e1b2f7..f73db8e3 100644 --- a/chain.hpp +++ b/chain.hpp @@ -3,156 +3,145 @@ #include "iterbase.hpp" -#include +#include +#include #include #include -#include -#include #include -#include +#include +#include namespace iter { // rather than a chain function, use a callable object to support // from_iterable class ChainMaker; - template - class Chained { +template +class Chained { + private: friend class ChainMaker; - private: - class ChainIterWrapperBase { - protected: - using ResultType = - iterator_deref>; - public: - virtual ~ChainIterWrapperBase() { } - virtual bool operator!=( - const ChainIterWrapperBase&) const = 0; - virtual bool operator==( - const ChainIterWrapperBase&) const = 0; - virtual ResultType operator*() = 0; - virtual ChainIterWrapperBase& operator++() = 0; - }; - - template - class ChainIterWrapper : public ChainIterWrapperBase { - private: - iterator_type sub_iter; - - public: - ChainIterWrapper(const iterator_type& iter) - : sub_iter{iter} - { } - - bool operator!=(const ChainIterWrapperBase& other) - const override { - return this->sub_iter != - static_cast( - other).sub_iter; - } - - bool operator==(const ChainIterWrapperBase& other) - const override { - return !(*this != - static_cast(other)); - } - - typename ChainIterWrapper::ResultType operator*() { - return *this->sub_iter; - } - - ChainIterWrapper& operator++() override { - ++this->sub_iter; - return *this; + static_assert(std::tuple_size>::value + == sizeof...(Is), + "tuple size != sizeof Is"); + + using IterTupType = iterator_tuple_type; + + using DerefType = + iterator_deref>; + + template + static DerefType get_and_deref(IterTupType& iters) { + return *std::get(iters); + } + + template + static void get_and_increment(IterTupType& iters) { + ++std::get(iters); + } + + template + static bool get_and_check_not_equal( + const IterTupType& lhs, const IterTupType& rhs) { + return std::get(lhs) != std::get(rhs); + } + + using DerefFunc = DerefType (*)(IterTupType&); + using IncFunc = void (*)(IterTupType&); + using NeqFunc = bool (*)(const IterTupType&, const IterTupType&); + + + constexpr static std::array derefers{{ + get_and_deref...}}; + + constexpr static std::array incrementers{{ + get_and_increment...}}; + + constexpr static std::array neq_comparers{{ + get_and_check_not_equal...}}; + + private: + TupType tup; + public: + Chained(TupType t) + : tup(t) + { } + + class Iterator { + private: + std::size_t index; + IterTupType iters; + IterTupType ends; + + void check_for_end_and_adjust() { + while (this->index < sizeof...(Is) + && !(neq_comparers[this->index]( + this->iters, this->ends))) { + ++this->index; } + } + public: + Iterator(std::size_t i, + IterTupType&& in_iters, + IterTupType&& in_ends) + : index{i}, + iters(in_iters), + ends(in_ends) + { + this->check_for_end_and_adjust(); + } + + decltype(auto) operator*() { + return derefers[this->index](this->iters); + } + + Iterator& operator++() { + incrementers[this->index](this->iters); + this->check_for_end_and_adjust(); + return *this; + } + + bool operator!=(const Iterator& other) const { + return this->index != other.index + || (this->index != sizeof...(Is) + && neq_comparers.at(this->index)( + this->iters,other.iters)); + } + + + }; + + Iterator begin() { + return { + 0, + IterTupType{std::begin(std::get(this->tup))...}, + IterTupType{std::end(std::get(this->tup))...} }; + } - - private: - using ArrayType = - std::array, - sizeof...(Is)>; - TupleType containers; - ArrayType end_iter_wrappers; - - Chained(TupleType&& tup_containers) - : containers(std::move(tup_containers)), - end_iter_wrappers{{std::make_unique< - ChainIterWrapper>>( - std::end(std::get(this->containers)))...}} - { } - - public: - class Iterator { - private: - using ArrayType = - std::array, - sizeof...(Is)>; - - ArrayType iter_wrappers; - const ArrayType& end_iter_wrappers; - std::size_t index; - - void check_index() { - while (this->index < iter_wrappers.size() - && *this->iter_wrappers[this->index] - == *this->end_iter_wrappers[this->index]) { - ++this->index; - } - } - - - public: - Iterator(ArrayType&& iters, ArrayType& ends, std::size_t i) - : iter_wrappers(std::move(iters)), - end_iter_wrappers{ends}, - index{i} - { - this->check_index(); - } - - Iterator(const Iterator& other) - : iter_wrappers{{ - // make this not so awful. - std::unique_ptr{new ChainIterWrapper>(dynamic_cast>&>(*std::get(other.iter_wrappers)))}... - }}, - end_iter_wrappers{other.end_iter_wrappers}, - index{other.index} - { } - - Iterator& operator++() { - ++*this->iter_wrappers[this->index]; - this->check_index(); - return *this; - } - - decltype(auto) operator*() { - return **this->iter_wrappers[this->index]; - } - - bool operator!=(const Iterator& other) const { - return this->index != other.index; - } + Iterator end() { + return { + sizeof...(Is), + IterTupType{std::end(std::get(this->tup))...}, + IterTupType{std::end(std::get(this->tup))...} }; - - - Iterator begin() { - ArrayType a{{ - std::make_unique< - ChainIterWrapper>>( - std::begin(std::get(this->containers)) - )...}}; - return {std::move(a), end_iter_wrappers, 0}; - } - - Iterator end() { - ArrayType a{{std::unique_ptr< - ChainIterWrapper>>{ - nullptr}...}}; - return {std::move(a), end_iter_wrappers, sizeof...(Is)}; - } - }; + } +}; + +template +constexpr std::array< + typename Chained::DerefFunc, sizeof...(Is)> + Chained::derefers; + +template +constexpr std::array< + typename Chained::IncFunc, sizeof...(Is)> + Chained::incrementers; + +template +constexpr std::array< + typename Chained::NeqFunc, sizeof...(Is)> + Chained::neq_comparers; template class ChainedFromIterable { From fbaab61bfeb222cad67b6956a8a35a02a54f2c07 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 12 Nov 2014 21:19:45 -0500 Subject: [PATCH 031/596] Makes absorb take universal refs again Because with just absorb(...) it tries to make copies, which makes sense. --- iterbase.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iterbase.hpp b/iterbase.hpp index c60713df..d0eade82 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -112,7 +112,8 @@ namespace iter { // function absorbing all arguments passed to it. used when // applying a function to a parameter pack but not passing the evaluated // results anywhere - void absorb(...) { } + template + void absorb(Ts&&...) { } namespace detail { template From b312fa0e4e54d3fa0d333b4f71b72c5f91fa6660 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 12 Nov 2014 21:30:38 -0500 Subject: [PATCH 032/596] replaces only .at() with [] --- chain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain.hpp b/chain.hpp index f73db8e3..50299693 100644 --- a/chain.hpp +++ b/chain.hpp @@ -104,7 +104,7 @@ class Chained { bool operator!=(const Iterator& other) const { return this->index != other.index || (this->index != sizeof...(Is) - && neq_comparers.at(this->index)( + && neq_comparers[this->index]( this->iters,other.iters)); } From 13924b0724677e4af38a03d86272172d31244a79 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:03:19 -0500 Subject: [PATCH 033/596] uses -std=c++14 --- catchtest/SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/catchtest/SConstruct b/catchtest/SConstruct index 0a8c1e35..cd23626e 100644 --- a/catchtest/SConstruct +++ b/catchtest/SConstruct @@ -4,7 +4,7 @@ env = Environment( ENV = os.environ, CXX='c++', CXXFLAGS= ['-g', '-Wall', '-Wextra', - '-pedantic', '-std=c++11', + '-pedantic', '-std=c++14', '-fdiagnostics-color=always', '-I/usr/local/include'], CPPPATH='..', From 79b89521e50e2b1ca1f0d681c1c6f5efd1b47743 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:03:46 -0500 Subject: [PATCH 034/596] corrects error in section description --- catchtest/test_imap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/catchtest/test_imap.cpp b/catchtest/test_imap.cpp index ba9ae171..9f7b8e4d 100644 --- a/catchtest/test_imap.cpp +++ b/catchtest/test_imap.cpp @@ -48,7 +48,7 @@ TEST_CASE("imap: works with lambda, callable, and function", "[imap]") { REQUIRE( v == vc ); } - SECTION("with function") { + SECTION("with callable") { auto im = imap(PlusOner{}, ns); Vec v(std::begin(im), std::end(im)); Vec vc = {11, 21, 31}; From bb76192dafeb4555f1937b326c779e7a13d7bbbe Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:08:08 -0500 Subject: [PATCH 035/596] drops references to functions, derives stditerator --- starmap.hpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 4a41cba9..8ff04994 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -4,30 +4,39 @@ #include "iterbase.hpp" #include +#include #include #include #include #include namespace iter { + // starmap with a container where T is one of tuple, pair, array template class StarMapper { private: Func func; Container container; + + using StarIterDeref = + std::remove_reference_t>()))>; + public: - StarMapper(Func f, Container c) - : func(f), + StarMapper(Func f, Container&& c) + : func(std::forward(f)), container(std::forward(c)) { } - class Iterator { + class Iterator + : public std::iterator + { private: Func func; iterator_type sub_iter; public: - Iterator(Func f, iterator_type iter) + Iterator(Func& f, iterator_type iter) : func(f), sub_iter(iter) { } @@ -36,11 +45,21 @@ namespace iter { return this->sub_iter != other.sub_iter; } + bool operator==(const Iterator& other) const { + return !(*this != other); + } + Iterator operator++() { ++this->sub_iter; return *this; } + Iterator operator++(int) { + auto ret = *this; + ++*this; + return ret; + } + decltype(auto) operator*() { return call_with_tuple(this->func, *this->sub_iter); } @@ -59,7 +78,7 @@ namespace iter { template StarMapper starmap_helper( - Func&& func, Container&& container, std::false_type) { + Func func, Container&& container, std::false_type) { return {std::forward(func), std::forward(container)}; } @@ -92,6 +111,7 @@ namespace iter { tup(std::forward(t)) { } + // TODO inherit from std::iterator class Iterator { private: Func& func; @@ -137,14 +157,14 @@ namespace iter { template TupleStarMapper starmap_helper_impl( - Func&& func, TupType&& tup, std::index_sequence) + Func func, TupType&& tup, std::index_sequence) { return {std::forward(func), std::forward(tup)}; } template auto starmap_helper( - Func&& func, TupType&& tup, std::true_type) { + Func func, TupType&& tup, std::true_type) { return starmap_helper_impl( std::forward(func), std::forward(tup), @@ -163,7 +183,7 @@ namespace iter { : public std::true_type { }; template - auto starmap(Func&& func, Seq&& sequence) { + auto starmap(Func func, Seq&& sequence) { return starmap_helper( std::forward(func), std::forward(sequence), @@ -171,7 +191,4 @@ namespace iter { } } - - - -#endif // #ifndef ITER_STARMAP_H_ +#endif From b9c5e27e62b263405dd610282f409f0bc1191376 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:24:57 -0500 Subject: [PATCH 036/596] adds basic starmap test --- catchtest/test_starmap.cpp | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 catchtest/test_starmap.cpp diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp new file mode 100644 index 00000000..015b966e --- /dev/null +++ b/catchtest/test_starmap.cpp @@ -0,0 +1,42 @@ +#include + +#include "helpers.hpp" + +#include +#include +#include + +#include "catch.hpp" + +using iter::starmap; + +namespace { + long f(long d, int i) { + return d * i; + } + + std::string g(const std::string& s, int i, double d) { + std::stringstream ss; + ss << s << ' ' << i << ' ' << d; + return ss.str(); + } +} + +TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") { + using Vec = const std::vector; + const std::vector> v1 = + {{1l, 2}, {3l, 11}, {6l, 7}}; + Vec vc = {2l, 33l, 42l}; + + SECTION("with function") { + auto sm = starmap(f, v1); + Vec v(std::begin(sm), std::end(sm)); + REQUIRE( v == vc ); + } + + SECTION("with lambda") { + auto sm = starmap([](long a, int b) { return a * b; }, v1); + Vec v(std::begin(sm), std::end(sm)); + REQUIRE( v == vc ); + } +} From 0a408fecc5900cfe6b09694d69ad0e4791cfb29f Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:32:55 -0500 Subject: [PATCH 037/596] builds starmap test --- catchtest/SConstruct | 1 + 1 file changed, 1 insertion(+) diff --git a/catchtest/SConstruct b/catchtest/SConstruct index cd23626e..36e14df3 100644 --- a/catchtest/SConstruct +++ b/catchtest/SConstruct @@ -38,6 +38,7 @@ progs = Split( slice sliding_window + starmap takewhile unique_everseen unique_justseen From d248ba210a63182f0b60553750ec529a2d2c1591 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:33:04 -0500 Subject: [PATCH 038/596] tests starmap a bit harder --- catchtest/test_starmap.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index 015b966e..e3e091a0 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -3,6 +3,7 @@ #include "helpers.hpp" #include +#include #include #include @@ -15,9 +16,9 @@ namespace { return d * i; } - std::string g(const std::string& s, int i, double d) { + std::string g(const std::string& s, int i, char c) { std::stringstream ss; - ss << s << ' ' << i << ' ' << d; + ss << s << ' ' << i << ' ' << c; return ss.str(); } } @@ -40,3 +41,16 @@ TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") { REQUIRE( v == vc ); } } + +TEST_CASE("starmap: list of tuples", "[starmap]") { + using Vec = const std::vector; + using T = std::tuple; + std::list li = + {T{"hey", 42, 'a'}, T{"there", 3, 'b'}, T{"yall", 5, 'c'}}; + + auto sm = starmap(g, li); + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {"hey 42 a", "there 3 b", "yall 5 c"}; + + REQUIRE( v == vc ); +} From d567e4513cfbd59c9b4428c9d938d161a7fd0401 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:47:27 -0500 Subject: [PATCH 039/596] tests starmap with a tuple of tuples --- catchtest/test_starmap.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index e3e091a0..378a8286 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -21,6 +21,16 @@ namespace { ss << s << ' ' << i << ' ' << c; return ss.str(); } + + struct Callable { + int operator()(int a, int b, int c) { + return a + b + c; + } + + int operator()(int a) { + return a; + } + }; } TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") { @@ -54,3 +64,13 @@ TEST_CASE("starmap: list of tuples", "[starmap]") { REQUIRE( v == vc ); } + +TEST_CASE("starmap: tuple of tuples", "[starmap]") { + using Vec = const std::vector; + auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); + auto sm = starmap(Callable{}, tup); + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {89, 7}; + + REQUIRE( v == vc ); +} From a39975c5334e809178205e03a1ac8f979d12bdcc Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 17:47:41 -0500 Subject: [PATCH 040/596] TupleStarMapper iter derives std::iterator --- starmap.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 8ff04994..3f8a64e2 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -105,14 +105,16 @@ namespace iter { constexpr static std::array callers{{ get_and_call_with_tuple...}}; + using TraitsValue = std::remove_reference_t; public: TupleStarMapper(Func f, TupType t) : func(std::forward(f)), tup(std::forward(t)) { } - // TODO inherit from std::iterator - class Iterator { + class Iterator + : public std::iterator + { private: Func& func; TupType& tup; From c7a08e30eb52d37bed0fee2e0c4dd2e3a2bb523b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 18:52:17 -0500 Subject: [PATCH 041/596] tests starmap with pair of array and tuple --- catchtest/test_starmap.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index 378a8286..fc59fd18 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -74,3 +74,16 @@ TEST_CASE("starmap: tuple of tuples", "[starmap]") { REQUIRE( v == vc ); } + +TEST_CASE("starmap: tuple of pairs", "[starmap]") { + using Vec = const std::vector; + auto p = std::make_pair(std::array{{15, 100, 2000}}, + std::make_tuple(16)); + Callable c; + auto sm = starmap(c, p); + + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {2115, 16}; + + REQUIRE( v == vc ); +} From 1c63201569b195f3f3b05247444ac7c3f44cbae3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:21:13 -0500 Subject: [PATCH 042/596] flattens zip longest --- zip_longest.hpp | 161 +++++++++++++++++++----------------------------- 1 file changed, 62 insertions(+), 99 deletions(-) diff --git a/zip_longest.hpp b/zip_longest.hpp index cc6705b9..98b20ec4 100644 --- a/zip_longest.hpp +++ b/zip_longest.hpp @@ -11,65 +11,51 @@ namespace iter { - template - using OptIterDeref = boost::optional>; - - template + template class ZippedLongest; - template - ZippedLongest zip_longest(Containers&&...); + template + ZippedLongest + zip_longest_impl(TupleType&&, std::index_sequence); - template - class ZippedLongest { - static_assert(!std::is_rvalue_reference::value, - "Itertools cannot be templated with rvalue references"); + template + class ZippedLongest { + private: + TupleType containers; + friend ZippedLongest zip_longest_impl( + TupleType&&, std::index_sequence); - friend ZippedLongest zip_longest( - Container&&, RestContainers&&...); + template + using OptType = boost::optional>>; - template - friend class ZippedLongest; + using ZipIterDeref = std::tuple...>; - private: - using OptType = OptIterDeref; - using ZipIterDeref = - std::tuple...>; - - Container container; - ZippedLongest rest_zipped; - ZippedLongest(Container&& container, RestContainers&&... rest) - : container(std::forward(container)), - rest_zipped{std::forward(rest)...} + ZippedLongest(TupleType&& in_containers) + : containers(std::move(in_containers)) { } - public: class Iterator : public std::iterator { private: - using RestIter = - typename ZippedLongest::Iterator; - - iterator_type iter; - iterator_type end; - RestIter rest_iter; + iterator_tuple_type iters; + iterator_tuple_type ends; public: - Iterator( - iterator_type it, - iterator_type in_end, - const RestIter& rest) - : iter{it}, - end{in_end}, - rest_iter{rest} + Iterator(iterator_tuple_type&& in_iters, + iterator_tuple_type&& in_ends) + : iters(std::move(in_iters)), + ends(std::move(in_ends)) { } Iterator& operator++() { - if (this->iter != this->end) { - ++this->iter; - } - ++this->rest_iter; + // increment every iterator that's not already at + // the end + absorb( + ((std::get(this->iters) != + std::get(this->ends)) ? + (++std::get(this->iters), 0) : 0)...); return *this; } @@ -80,8 +66,15 @@ namespace iter { } bool operator!=(const Iterator& other) const { - return this->iter != other.iter || - this->rest_iter != other.rest_iter; + if (sizeof...(Is) == 0) return false; + + bool results[] = { false, + (std::get(this->iters) != + std::get(other.iters))... + }; + return std::any_of( + std::begin(results), std::end(results), + [](bool b){ return b; } ); } bool operator==(const Iterator& other) const { @@ -89,72 +82,42 @@ namespace iter { } ZipIterDeref operator*() { - if (this->iter != this->end) { - return std::tuple_cat( - std::tuple{{*this->iter}}, - *this->rest_iter); - } else { - return std::tuple_cat( - std::tuple{{}}, - *this->rest_iter); - } + return ZipIterDeref{ + ((std::get(this->iters) != + std::get(this->ends)) + ? OptType{*std::get(this->iters)} + : OptType{})...}; } }; Iterator begin() { - return {std::begin(this->container), - std::end(this->container), - std::begin(this->rest_zipped)}; + return { + iterator_tuple_type{ + std::begin(std::get(this->containers))...}, + iterator_tuple_type{ + std::end(std::get(this->containers))...}}; } Iterator end() { - return {std::end(this->container), - std::end(this->container), - std::end(this->rest_zipped)}; + return { + iterator_tuple_type{ + std::end(std::get(this->containers))...}, + iterator_tuple_type{ + std::end(std::get(this->containers))...}}; } - }; - - - template <> - class ZippedLongest<> { - public: - class Iterator - : public std::iterator> - { - public: - Iterator& operator++() { - return *this; - } +}; - constexpr Iterator operator++(int) { - return *this; - } - - constexpr bool operator!=(const Iterator&) const { - return false; - } - - constexpr bool operator==(const Iterator&) const { - return true; - } - - constexpr std::tuple<> operator*() { - return {}; - } - }; - - constexpr Iterator begin() { - return {}; - } - - constexpr Iterator end() { - return {}; - } - }; + template + ZippedLongest zip_longest_impl( + TupleType&& in_containers, std::index_sequence) { + return {std::move(in_containers)}; + } template - ZippedLongest zip_longest(Containers&&... containers) { - return {std::forward(containers)...}; + auto zip_longest(Containers&&... containers) { + return zip_longest_impl(std::tuple{ + std::forward(containers)...}, + std::index_sequence_for{}); } } From f95dba8572ec2600b1b83b95f5b39d415be45822 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:40:05 -0500 Subject: [PATCH 043/596] uses c++14 type aliases --- accumulate.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/accumulate.hpp b/accumulate.hpp index 8df2e409..c57d177c 100644 --- a/accumulate.hpp +++ b/accumulate.hpp @@ -38,10 +38,10 @@ namespace iter { // AccumVal must be default constructible using AccumVal = - typename std::remove_reference< - typename std::result_of, - iterator_deref)>::type>::type; + iterator_deref)>>; static_assert( std::is_default_constructible::value, "Cannot accumulate a non-default constructible type"); @@ -125,12 +125,12 @@ namespace iter { template auto accumulate(Container&& container) -> decltype(accumulate(std::forward(container), - std::plus>::type>{})) + std::plus>>{})) { return accumulate(std::forward(container), - std::plus>::type>{}); + std::plus>>{}); } template From 0fd65dfc500c654823c977f0261fa456fab9c67b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:41:09 -0500 Subject: [PATCH 044/596] uses c++14 type aliases --- combinations.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/combinations.hpp b/combinations.hpp index a2cfeda2..6f8b3dd9 100644 --- a/combinations.hpp +++ b/combinations.hpp @@ -46,7 +46,7 @@ namespace iter { { private: constexpr static const int COMPLETE = -1; - typename std::remove_reference::type *container_p; + std::remove_reference_t *container_p; CombIteratorDeref indices; int steps{}; From 36f8e3856c71cb044bbe95e4a0f56dd15aacc6be Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:41:58 -0500 Subject: [PATCH 045/596] uses c++14 type aliases --- combinations_with_replacement.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/combinations_with_replacement.hpp b/combinations_with_replacement.hpp index bfb8a9b1..96ea9af0 100644 --- a/combinations_with_replacement.hpp +++ b/combinations_with_replacement.hpp @@ -52,7 +52,7 @@ namespace iter { { private: constexpr static const int COMPLETE = -1; - typename std::remove_reference::type *container_p; + std::remove_reference_t *container_p; CombIteratorDeref indices; int steps; From 516e707db264ee6544cab39e0a539547bc661bf0 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:43:10 -0500 Subject: [PATCH 046/596] uses c++14 type aliases --- groupby.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/groupby.hpp b/groupby.hpp index 42768202..dcda1fda 100644 --- a/groupby.hpp +++ b/groupby.hpp @@ -32,8 +32,8 @@ namespace iter { friend GroupBy, KF> groupby( std::initializer_list, KF); - using key_func_ret = typename - std::result_of)>::type; + using key_func_ret = + std::result_of_t)>; GroupBy(Container&& container, KeyFunc key_func) : container(std::forward(container)), From e31a0db04317d4328fabd796f00c632e9a768648 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:47:45 -0500 Subject: [PATCH 047/596] uses c++14 type aliases --- iterbase.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 52f5d807..95f369ef 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -30,7 +30,7 @@ namespace iter { template using iterator_traits_deref = - typename std::remove_reference>::type; + std::remove_reference_t>; // iterator_type is the type of C's iterator template @@ -48,11 +48,11 @@ namespace iter { template struct is_random_access_iter::iterator_category, - std::random_access_iterator_tag>::value, - void>::type> : std::true_type { }; + std::random_access_iterator_tag>::value + >> : std::true_type { }; template using has_random_access_iter = is_random_access_iter>; From 3d3a0ec9767059ed8854d79f854cfe66b5032517 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:49:55 -0500 Subject: [PATCH 048/596] uses c++14 type aliases --- powerset.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerset.hpp b/powerset.hpp index 964b0651..eb58f909 100644 --- a/powerset.hpp +++ b/powerset.hpp @@ -29,7 +29,7 @@ namespace iter { std::input_iterator_tag, CombinatorType> { private: - typename std::remove_reference::type *container_p; + std::remove_reference_t *container_p; std::size_t set_size; std::unique_ptr comb; iterator_type comb_iter; From 2651b6603849b7d64e5ddbe930cc82f4fccdd617 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:53:23 -0500 Subject: [PATCH 049/596] shortens tag dispatch --- range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/range.hpp b/range.hpp index f0e7048c..9ce252b8 100644 --- a/range.hpp +++ b/range.hpp @@ -121,7 +121,7 @@ namespace iter { // So, if an iterator is not equal to that, it is valid bool operator!=(const Iterator& other) const { return not_equal_to( - other, typename std::is_unsigned::type()); + other, std::is_unsigned{}); } bool operator==(const Iterator& other) const { From ead0e699bc642348372395485ae29f835b004094 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 20:54:21 -0500 Subject: [PATCH 050/596] uses c++14 type aliases --- repeat.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repeat.hpp b/repeat.hpp index 03ecadce..7a9c6adc 100644 --- a/repeat.hpp +++ b/repeat.hpp @@ -24,7 +24,7 @@ namespace iter { friend Repeater repeat(T&&); friend Repeater repeat(T&&, int); private: - using TPlain = typename std::remove_reference::type; + using TPlain = std::remove_reference_t; T elem; int count; From 816e70054fbcd3ae8692eed087ffa46d4b9755dc Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 8 Feb 2015 21:22:03 -0500 Subject: [PATCH 051/596] uses auto funcs and init capture --- unique_everseen.hpp | 47 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/unique_everseen.hpp b/unique_everseen.hpp index ec95eb34..6a095fe6 100644 --- a/unique_everseen.hpp +++ b/unique_everseen.hpp @@ -10,45 +10,26 @@ #include #include -namespace iter -{ - //the container type must be usable in an unordered_map to achieve constant - //performance checking if it has ever been seen +namespace iter { template - auto unique_everseen(Container&& container) - -> Filter)>,Container> - { - using elem_t = iterator_deref; - std::unordered_set::type> elem_seen; - - std::function func = - //has to be captured by value because it goes out of scope when the - //function returns - [elem_seen](elem_t e) mutable - { - if (elem_seen.find(e) == std::end(elem_seen)){ - elem_seen.insert(e); - return true; - } else { - return false; - } + auto unique_everseen(Container&& container) { + using elem_type = iterator_deref; + auto func = + [ + elem_seen = std::unordered_set>() + ] (const elem_type& e) mutable { + return elem_seen.insert(e).second; }; return filter(func, std::forward(container)); } template - auto unique_everseen(std::initializer_list il) - -> Filter, std::initializer_list> - { - std::unordered_set elem_seen; - std::function func = [elem_seen](const T& e) mutable - { - if (elem_seen.find(e) == std::end(elem_seen)){ - elem_seen.insert(e); - return true; - } else { - return false; - } + auto unique_everseen(std::initializer_list il) { + auto func = + [ + elem_seen = std::unordered_set() + ] (const T& e) mutable { + return elem_seen.insert(e).second; }; return filter(func, il); } From eba0d63f1522ce107608cdfaf861919f7dfb6edb Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:28:19 -0500 Subject: [PATCH 052/596] return type deduction --- accumulate.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/accumulate.hpp b/accumulate.hpp index c57d177c..6186d869 100644 --- a/accumulate.hpp +++ b/accumulate.hpp @@ -123,11 +123,7 @@ namespace iter { } template - auto accumulate(Container&& container) -> - decltype(accumulate(std::forward(container), - std::plus>>{})) - { + auto accumulate(Container&& container) { return accumulate(std::forward(container), std::plus>>{}); @@ -142,9 +138,7 @@ namespace iter { } template - auto accumulate(std::initializer_list il) -> - decltype(accumulate(std::move(il), std::plus{})) - { + auto accumulate(std::initializer_list il) { return accumulate(std::move(il), std::plus{}); } From f5c4cf055b7540f30c500bf140b7f290315d9b85 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:29:49 -0500 Subject: [PATCH 053/596] uses return type deduction --- count.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/count.hpp b/count.hpp index e0bc7cd0..4ef0a3be 100644 --- a/count.hpp +++ b/count.hpp @@ -9,13 +9,13 @@ namespace iter { using DefaultRangeType = long; - auto count() -> decltype(range(DefaultRangeType(0), DefaultRangeType(0))) { + auto count() { return range(DefaultRangeType(0), std::numeric_limits::max()); } template - auto count(T start, T step) -> decltype(range(start, start, start)) { + auto count(T start, T step) { // if step is < 0, set the stop to numeric min, otherwise numeric max T stop = step < T(0) ? std::numeric_limits::min() : std::numeric_limits::max(); @@ -23,7 +23,7 @@ namespace iter { } template - auto count(T start) -> decltype(range(start, start)) { + auto count(T start) { return count(start, T(1)); } } From 16a88e32c99d2ccfb3a2b7a7f2ba5d631bcfa163 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:31:52 -0500 Subject: [PATCH 054/596] uses return type deduction --- filter.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/filter.hpp b/filter.hpp index fdefe612..b66da5fe 100644 --- a/filter.hpp +++ b/filter.hpp @@ -143,20 +143,14 @@ namespace iter { template - auto filter(Container&& container) -> - decltype(filter( - detail::BoolTester(), - std::forward(container))) { + auto filter(Container&& container) { return filter( detail::BoolTester(), std::forward(container)); } template - auto filter(std::initializer_list il) -> - decltype(filter( - detail::BoolTester>(), - std::move(il))) { + auto filter(std::initializer_list il) { return filter( detail::BoolTester>(), std::move(il)); From f3e0f261b5f1d7a56813371e8e07ca9ddd426c78 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:35:16 -0500 Subject: [PATCH 055/596] uses return type deduction --- filterfalse.hpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/filterfalse.hpp b/filterfalse.hpp index 3bad5fa0..f7530ab9 100644 --- a/filterfalse.hpp +++ b/filterfalse.hpp @@ -53,11 +53,7 @@ namespace iter { // the bool result of the function. The PredicateFlipper is then passed // to the normal filter() function template - auto filterfalse(FilterFunc filter_func, Container&& container) -> - decltype(filter( - detail::PredicateFlipper( - filter_func), - std::forward(container))) { + auto filterfalse(FilterFunc filter_func, Container&& container) { return filter( detail::PredicateFlipper(filter_func), std::forward(container)); @@ -66,10 +62,7 @@ namespace iter { // Single argument version, uses a BoolFlipper to reverse the truthiness // of an object template - auto filterfalse(Container&& container) -> - decltype(filter( - detail::BoolFlipper(), - std::forward(container))) { + auto filterfalse(Container&& container) { return filter( detail::BoolFlipper(), std::forward(container)); @@ -79,23 +72,18 @@ namespace iter { //specializations for initializer_lists template - auto filterfalse(FilterFunc filter_func, std::initializer_list container) -> - decltype(filter( - detail::PredicateFlipper>( - filter_func), - std::move(container))) { + auto filterfalse(FilterFunc filter_func, + std::initializer_list container) { return filter( - detail::PredicateFlipper>(filter_func), + detail::PredicateFlipper>( + filter_func), std::move(container)); } // Single argument version, uses a BoolFlipper to reverse the truthiness // of an object template - auto filterfalse(std::initializer_list container) -> - decltype(filter( - detail::BoolFlipper>(), - std::move(container))) { + auto filterfalse(std::initializer_list container) { return filter( detail::BoolFlipper>(), std::move(container)); From 944d74cc45069157044fc61ffc0b9e14d8181de3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:36:51 -0500 Subject: [PATCH 056/596] uses return type deduction --- groupby.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/groupby.hpp b/groupby.hpp index dcda1fda..f4a59e64 100644 --- a/groupby.hpp +++ b/groupby.hpp @@ -258,9 +258,7 @@ namespace iter { template - auto groupby(Container&& container) -> - decltype(groupby(std::forward(container), - ItemReturner())) { + auto groupby(Container&& container) { return groupby(std::forward(container), ItemReturner()); } @@ -274,9 +272,7 @@ namespace iter { template - auto groupby(std::initializer_list il) -> - decltype(groupby(std::move(il), - ItemReturner>())) { + auto groupby(std::initializer_list il) { return groupby( std::move(il), ItemReturner>()); From 9b120bb1b4d8010ec4dbf4ea5baa9e35ad1d487f Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 15:39:29 -0500 Subject: [PATCH 057/596] uses return type deduction --- sorted.hpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sorted.hpp b/sorted.hpp index 5dbbdc9b..7caa2731 100644 --- a/sorted.hpp +++ b/sorted.hpp @@ -66,13 +66,10 @@ namespace iter { } template - auto sorted(Container&& container) -> - decltype(sorted(std::forward(container), - std::less>())) - { - return sorted(std::forward(container), - std::less>()); - } + auto sorted(Container&& container) { + return sorted(std::forward(container), + std::less>()); + } } From 2e119bec14cee30d9bdfde1c78298e4db1046554 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 16:08:08 -0500 Subject: [PATCH 058/596] uses return type deduction --- iteratoriterator.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/iteratoriterator.hpp b/iteratoriterator.hpp index 5bd807bc..10faa0ee 100644 --- a/iteratoriterator.hpp +++ b/iteratoriterator.hpp @@ -67,11 +67,11 @@ namespace iter { return ret; } - auto operator*() -> decltype(**sub_iter) { + decltype(auto) operator*() { return **this->sub_iter; } - auto operator->() -> decltype(*sub_iter) { + decltype(auto) operator->() { return *this->sub_iter; } @@ -112,7 +112,7 @@ namespace iter { return this->sub_iter - rhs.sub_iter; } - auto operator[](Diff idx) -> decltype(*sub_iter[idx]) { + decltype(auto) operator[](Diff idx) { return *sub_iter[idx]; } @@ -156,24 +156,22 @@ namespace iter { : container(sz, val) { } - auto at(size_type pos) -> decltype(*container.at(pos)) { + decltype(auto) at(size_type pos) { return *container.at(pos); } - auto at(size_type pos) const -> decltype(*container.at(pos)) { + decltype(auto) at(size_type pos) const { return *container.at(pos); } - auto operator[](size_type pos) + decltype(auto) operator[](size_type pos) noexcept(noexcept(*container[pos])) - -> decltype(*container[pos]) { return *container[pos]; } - auto operator[](size_type pos) const + decltype(auto) operator[](size_type pos) const noexcept(noexcept(*container[pos])) - -> decltype(*container[pos]) { return *container[pos]; } From bbcb5cd06134163d2d57588e7b90c2344a36fbd3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 9 Feb 2015 16:30:35 -0500 Subject: [PATCH 059/596] tests that starmap moves and binds correctly --- catchtest/test_starmap.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index fc59fd18..ce8d40c6 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -87,3 +87,11 @@ TEST_CASE("starmap: tuple of pairs", "[starmap]") { REQUIRE( v == vc ); } + +TEST_CASE("starmap: moves rvalues, binds to lvalues", "[starmap]") { + itertest::BasicIterable> bi{}; + starmap(Callable{}, bi); + REQUIRE_FALSE( bi.was_moved_from() ); + starmap(Callable{}, std::move(bi)); + REQUIRE( bi.was_moved_from() ); +} From 8161f3902519486b5c116bb96e31cca8f56279e4 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 18 Feb 2015 00:23:11 -0500 Subject: [PATCH 060/596] uses Func* in starmap iterator --- starmap.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 3f8a64e2..15119dc2 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -33,11 +33,11 @@ namespace iter { : public std::iterator { private: - Func func; + Func *func; iterator_type sub_iter; public: Iterator(Func& f, iterator_type iter) - : func(f), + : func(&f), sub_iter(iter) { } @@ -61,7 +61,7 @@ namespace iter { } decltype(auto) operator*() { - return call_with_tuple(this->func, *this->sub_iter); + return call_with_tuple(*this->func, *this->sub_iter); } }; From ec1d73153b09ccd342f9eb5a9bced3d91548f7e0 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 18 Feb 2015 00:24:14 -0500 Subject: [PATCH 061/596] eliminates extra copy of iterator --- starmap.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 15119dc2..3e1ec9fc 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -36,9 +36,9 @@ namespace iter { Func *func; iterator_type sub_iter; public: - Iterator(Func& f, iterator_type iter) + Iterator(Func& f, iterator_type&& iter) : func(&f), - sub_iter(iter) + sub_iter(std::move(iter)) { } bool operator!=(const Iterator& other) const { From 7c096f05f4a918eeadbb16d44f99f0a8b64a9599 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 18 Feb 2015 00:37:52 -0500 Subject: [PATCH 062/596] corrects ++ and == in starmap iterators prefix ++ was returning Iterator instead of Iterator& --- starmap.hpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 3e1ec9fc..138dba75 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -49,7 +49,7 @@ namespace iter { return !(*this != other); } - Iterator operator++() { + Iterator& operator++() { ++this->sub_iter; return *this; } @@ -131,14 +131,24 @@ namespace iter { return callers[this->index](this->func, this->tup); } - Iterator operator++() { + Iterator& operator++() { ++this->index; return *this; } + Iterator operator++(int) { + auto ret = *this; + ++*this; + return ret; + } + bool operator!=(const Iterator& other) const { return this->index != other.index; } + + bool operator==(const Iterator& other) const { + return !(*this != other); + } }; Iterator begin() { From 2d6a5aa2991d83bd8bcc56a2a0a35219f75d3aa2 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 18 Feb 2015 00:40:28 -0500 Subject: [PATCH 063/596] explicitly defaults default ctors for DerefHolder --- iterbase.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iterbase.hpp b/iterbase.hpp index 6ab8958a..48c987fd 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -198,6 +198,7 @@ namespace iter { std::unique_ptr item_p; public: + DerefHolder() = default; DerefHolder(const DerefHolder& other) : item_p{other.item_p ? new TPlain(*other.item_p) : nullptr} { } @@ -244,6 +245,7 @@ namespace iter { typename std::remove_reference::type *item_p =nullptr; public: + DerefHolder() = default; T get() { return *this->item_p; } From 5a11a2c5c5310cf2a75d9bc4ea70dbe6e57c9de4 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 18 Feb 2015 11:01:22 -0500 Subject: [PATCH 064/596] forwards the tuple elements to the called function --- iterbase.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/iterbase.hpp b/iterbase.hpp index 48c987fd..7a354802 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -162,7 +162,10 @@ namespace iter { template decltype(auto) call_with_tuple_impl(Func&& mf, TupleType&& tup, std::index_sequence) { - return mf(std::get(tup)...); + return mf(std::forward< + std::tuple_element_t< + Is, std::remove_reference_t> + >(std::get(tup))...); } } From a755f8b906372b9557d369481802635120ea5fe4 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 23 Feb 2015 10:35:16 -0500 Subject: [PATCH 065/596] tests normal starmap iterator requirements --- catchtest/test_starmap.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index ce8d40c6..b26de6c5 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -95,3 +95,10 @@ TEST_CASE("starmap: moves rvalues, binds to lvalues", "[starmap]") { starmap(Callable{}, std::move(bi)); REQUIRE( bi.was_moved_from() ); } + +TEST_CASE("starmap: iterator meets requirements", "[starmap]") { + std::string s{}; + const std::vector> v1; + auto sm = starmap([](long a, int b) { return a * b; }, v1); + REQUIRE( itertest::IsIterator::value ); +} From 57ef52338ca340ace4b778ebf45347e3a865b4cc Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 23 Feb 2015 10:41:54 -0500 Subject: [PATCH 066/596] tests TupleStarMapper's iterator requirements --- catchtest/test_starmap.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/catchtest/test_starmap.cpp b/catchtest/test_starmap.cpp index b26de6c5..994f96b7 100644 --- a/catchtest/test_starmap.cpp +++ b/catchtest/test_starmap.cpp @@ -102,3 +102,10 @@ TEST_CASE("starmap: iterator meets requirements", "[starmap]") { auto sm = starmap([](long a, int b) { return a * b; }, v1); REQUIRE( itertest::IsIterator::value ); } + +TEST_CASE("starmap: tuple of tuples iterator meets requirements", + "[starmap]") { + auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); + auto sm = starmap(Callable{}, tup); + REQUIRE( itertest::IsIterator::value ); +} From 8f284acb26acbe0b4747b9ceffea80b9b93e1933 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 23 Feb 2015 11:20:24 -0500 Subject: [PATCH 067/596] replaces references with pointers in starmap iter to make the iterator assignable --- starmap.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/starmap.hpp b/starmap.hpp index 138dba75..978fab23 100644 --- a/starmap.hpp +++ b/starmap.hpp @@ -116,19 +116,19 @@ namespace iter { : public std::iterator { private: - Func& func; - TupType& tup; + Func *func; + std::remove_reference_t *tup; std::size_t index; public: Iterator(Func& f, TupType& t, std::size_t i) - : func{f}, - tup{t}, + : func{&f}, + tup{&t}, index{i} { } decltype(auto) operator*() { - return callers[this->index](this->func, this->tup); + return callers[this->index](*this->func, *this->tup); } Iterator& operator++() { From 46c5c68c9cd670d2ded40ffa495bd7e7009c6601 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 23 Feb 2015 11:24:20 -0500 Subject: [PATCH 068/596] uses c++14 aliases --- groupby.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/groupby.hpp b/groupby.hpp index a50730bc..b81e1eeb 100644 --- a/groupby.hpp +++ b/groupby.hpp @@ -179,7 +179,7 @@ namespace iter { iterator_traits_deref> { private: - typename std::remove_reference::type *key; + std::remove_reference_t *key; Group *group_p; bool not_at_end() { From 203e881080143f35b0fae9ebf3289066ad3a81ee Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 23 Feb 2015 11:24:36 -0500 Subject: [PATCH 069/596] uses c++14 aliases --- iterbase.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 42efd0b7..ce97260d 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -196,7 +196,7 @@ namespace iter { static_assert(!std::is_lvalue_reference::value, "Non-lvalue-ref specialization used for lvalue ref type"); // it could still be an rvalue reference - using TPlain = typename std::remove_reference::type; + using TPlain = std::remove_reference_t; std::unique_ptr item_p; @@ -247,7 +247,7 @@ namespace iter { static_assert(std::is_lvalue_reference::value, "lvalue specialization handling non-lvalue-ref type"); - typename std::remove_reference::type *item_p =nullptr; + std::remove_reference_t *item_p =nullptr; public: DerefHolder() = default; From dfee40438f886f7a8f067873b5c0a54eed88bf06 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 4 Apr 2015 18:25:12 -0700 Subject: [PATCH 070/596] adds starmap to the docs --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index a0623a8b..9cd3a1f4 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ evaluation wherever possible. [repeat](#repeat)
[count](#count)
[groupby](#groupby)
+[starmap](#starmap)
[accumulate](#accumulate)
[compress](#compress)
[sorted](#sorted)
@@ -287,6 +288,48 @@ for (auto&& gb : groupby(vec, [] (const string &s) {return s.length(); })) { It just iterates through, making a new group each time there is a key change. Thus, if the the group is unsorted, the same key may appear multiple times. +starmap +------- + +Takes a sequence of tuple-like objects (anything that works with `std::get`) +and unpacks each object into individual arguments for each function call. +The below example takes a `vector` of `pairs` of ints, and passes them +to a function expecting two ints, with the elements of the `pair` being +the first and second arguments to the function. + +```c++ +vector> v = {{2, 3}, {5, 2}, {3, 4}}; // {base, exponent} +for (auto&& i : starmap([](int b, int e){return pow(b, e);}, v)) { + // ... +} +``` + +`starmap` can also work over a tuple-like object of tuple-like objects even +when the contained objects are different as long as the functor works with +multiple types of calls. For example, a `Callable` struct with overloads +for its `operator()` will work as long as all overloads have the same +return type + +```c++ +struct Callable { + int operator()(int i) const; + int operator()(int i, char c) const; + int operator()(double d, int i, char c) const; +}; +``` + +This will work with a tuple of mixed types + +```c++ +auto t = make_tuple( + make_tuple(5), // first form + make_pair(3, 'c'), // second + make_tuple(1.0, 1, '1')); // third +for (auto&& i : starmap(Callable{}, t)) { + // ... +} +``` + accumulate ------- Differs from `std::accumulate` (which in my humble opinion should be named From ef1ae7513b98dd57e090667d1e8ed9eab9b6ac3b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sat, 4 Apr 2015 19:00:02 -0700 Subject: [PATCH 071/596] tests that sorted iter meets requirements --- catchtest/test_sorted.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/catchtest/test_sorted.cpp b/catchtest/test_sorted.cpp index 918dec7d..843501b7 100644 --- a/catchtest/test_sorted.cpp +++ b/catchtest/test_sorted.cpp @@ -171,3 +171,9 @@ TEST_CASE("sorted: doesn't move or copy elements of iterable", "[sorted]") { (void)i; } } + +TEST_CASE("sorted: iterator meets requirements", "[sorted]") { + Vec v; + auto r = sorted(v); + REQUIRE( itertest::IsIterator::value ); +} From 8b58b1d86762729126e5b2cc7c7a27c172e1475c Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 00:06:49 -0700 Subject: [PATCH 072/596] removes old tests --- tests/.gitignore | 5 - tests/SConstruct | 52 --------- tests/samples.hpp | 98 ---------------- tests/testaccumulate.cpp | 33 ------ tests/testchain.cpp | 67 ----------- tests/testchainfromiterable.cpp | 28 ----- tests/testcombinations.cpp | 75 ------------- tests/testcombinations_with_replacement.cpp | 55 --------- tests/testcommand_chains.cpp | 78 ------------- tests/testcompress.cpp | 67 ----------- tests/testcount.cpp | 38 ------- tests/testcycle.cpp | 70 ------------ tests/testdropwhile.cpp | 35 ------ tests/testenumerate.cpp | 60 ---------- tests/testfilter.cpp | 83 -------------- tests/testfilterfalse.cpp | 93 --------------- tests/testgroupby.cpp | 109 ------------------ tests/testgrouper.cpp | 51 --------- tests/testimap.cpp | 45 -------- tests/testpermutations.cpp | 60 ---------- tests/testpowerset.cpp | 44 -------- tests/testproduct.cpp | 77 ------------- tests/testrange.cpp | 83 -------------- tests/testrepeat.cpp | 31 ----- tests/testreversed.cpp | 43 ------- tests/testslice.cpp | 81 -------------- tests/testsliding_window.cpp | 53 --------- tests/testsorted.cpp | 36 ------ tests/teststarmap.cpp | 83 -------------- tests/testtakewhile.cpp | 32 ------ tests/testunique_everseen.cpp | 41 ------- tests/testunique_justseen.cpp | 35 ------ tests/testzip.cpp | 118 -------------------- tests/testzip_longest.cpp | 96 ---------------- 34 files changed, 2055 deletions(-) delete mode 100644 tests/.gitignore delete mode 100644 tests/SConstruct delete mode 100644 tests/samples.hpp delete mode 100644 tests/testaccumulate.cpp delete mode 100644 tests/testchain.cpp delete mode 100644 tests/testchainfromiterable.cpp delete mode 100644 tests/testcombinations.cpp delete mode 100644 tests/testcombinations_with_replacement.cpp delete mode 100644 tests/testcommand_chains.cpp delete mode 100644 tests/testcompress.cpp delete mode 100644 tests/testcount.cpp delete mode 100644 tests/testcycle.cpp delete mode 100644 tests/testdropwhile.cpp delete mode 100644 tests/testenumerate.cpp delete mode 100644 tests/testfilter.cpp delete mode 100644 tests/testfilterfalse.cpp delete mode 100644 tests/testgroupby.cpp delete mode 100644 tests/testgrouper.cpp delete mode 100644 tests/testimap.cpp delete mode 100644 tests/testpermutations.cpp delete mode 100644 tests/testpowerset.cpp delete mode 100644 tests/testproduct.cpp delete mode 100644 tests/testrange.cpp delete mode 100644 tests/testrepeat.cpp delete mode 100644 tests/testreversed.cpp delete mode 100644 tests/testslice.cpp delete mode 100644 tests/testsliding_window.cpp delete mode 100644 tests/testsorted.cpp delete mode 100644 tests/teststarmap.cpp delete mode 100644 tests/testtakewhile.cpp delete mode 100644 tests/testunique_everseen.cpp delete mode 100644 tests/testunique_justseen.cpp delete mode 100644 tests/testzip.cpp delete mode 100644 tests/testzip_longest.cpp diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index a77d502e..00000000 --- a/tests/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.o -*.swp -test* -!test*.cpp -.sconsign.dblite diff --git a/tests/SConstruct b/tests/SConstruct deleted file mode 100644 index 8e344b2b..00000000 --- a/tests/SConstruct +++ /dev/null @@ -1,52 +0,0 @@ -import os - -env = Environment( - ENV = {'PATH' : os.environ['PATH']}, - CXX='c++', - CXXFLAGS= ['-g', '-Wall', '-Wextra', - '-pedantic', '-std=c++14', - '-fdiagnostics-color=always', - '-I/usr/local/include'], - CPPPATH='..', - LINKFLAGS='-L/usr/local/lib') - -# allows highighting to print to terminal from compiler output -env['ENV']['TERM'] = os.environ['TERM'] - -progs = Split(''' - accumulate - cycle - enumerate - range - zip - slice - reversed - filter - repeat - takewhile - dropwhile - zip_longest - product - permutations - compress - combinations_with_replacement - combinations - powerset - sliding_window - imap - starmap - count - filterfalse - grouper - chain - chainfromiterable - groupby - sorted - unique_justseen - unique_everseen - command_chains - ''') - - -for p in progs: - env.Program('test{0}.cpp'.format(p)) diff --git a/tests/samples.hpp b/tests/samples.hpp deleted file mode 100644 index 820d2c1e..00000000 --- a/tests/samples.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef ITERTOOLS_SAMPLE_CLASSES_HPP -#define ITERTOOLS_SAMPLE_CLASSES_HPP - -#include -#include -#include - -namespace itertest { - class MoveOnly { - private: - int i; // not an aggregate - public: - MoveOnly(int v) - : i{v} - { } - - MoveOnly(const MoveOnly&) = delete; - MoveOnly& operator=(const MoveOnly&) = delete; - - MoveOnly(MoveOnly&& other) noexcept - : i{other.i} - { } - - MoveOnly& operator=(MoveOnly&& other) noexcept { - this->i = other.i; - return *this; - } - - // for std::next_permutation compatibility - friend bool operator<(const MoveOnly& lhs, const MoveOnly& rhs) { - return lhs.i < rhs.i; - } - - friend std::ostream& operator<<( - std::ostream& out, const MoveOnly& self) { - return out << self.i; - } - - }; - - class DerefByValue { - private: - static constexpr std::size_t N = 3; - int array[N] = {0, 1, 2}; - public: - DerefByValue() = default; - - class Iterator { - private: - int *current; - public: - Iterator() = default; - Iterator(int *p) - : current{p} - { } - - bool operator!=(const Iterator& other) const { - return this->current != other.current; - } - - // for testing, iterator derefences to an int instead of - // an int& - int operator*() { - return *this->current; - } - - Iterator& operator++() { - ++this->current; - return *this; - } - }; - - Iterator begin() { - return {this->array}; - } - - Iterator end() { - return {this->array + N}; - } - }; - - class DerefByValueFancy { - private: - static constexpr std::size_t N = 3; - int array[N] = {0, 1, 2}; - public: - DerefByValueFancy() = default; - - int *begin() { - return this->array; - } - - int *end() { - return this->array + N; - } - }; -} -#endif // #ifndef ITERTOOLS_SAMPLE_CLASSES_HPP diff --git a/tests/testaccumulate.cpp b/tests/testaccumulate.cpp deleted file mode 100644 index 2321ffca..00000000 --- a/tests/testaccumulate.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -#include -#include - -int main() { - std::vector vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - for (auto v : iter::accumulate(vec, [](int a, int b){return a - b;})) { - std::cout << v << '\n'; - } - for (auto v : iter::accumulate(iter::range(10), - [](int a, int b){return a - b;})) { - std::cout << v << '\n'; - } - for (auto v : iter::accumulate({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, - [](int a, int b){return a - b;})) { - std::cout << v << '\n'; - } - - for (auto v : iter::accumulate(iter::range(10))) { - std::cout << v << '\n'; - } - for (auto v : iter::accumulate({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})) { - std::cout << v << '\n'; - } - - for (auto v : iter::accumulate(std::vector{1,2,3,4,5,6,7,8,9})) { - std::cout << v << '\n'; - } - - return 0; -} diff --git a/tests/testchain.cpp b/tests/testchain.cpp deleted file mode 100644 index 3dfde3d1..00000000 --- a/tests/testchain.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -using iter::chain; -using il = std::initializer_list; - -int main() { - - { - std::vector ivec{1, 4, 7, 9}; - std::vector lvec{100, 200, 300, 400, 500, 600}; - - for (auto e : chain(ivec, lvec)) { - std::cout << e << std::endl; - } - - auto c = chain(ivec, lvec); - auto it = std::begin(c); - auto it2 = std::begin(c); - it = it2; - } - { - std::vector empty{}; - std::vector vec1{1,2,3,4,5,6}; - std::array arr1{{7,8,9,10}}; - std::array arr2{{11,12,13}}; - std::cout << std::endl << "Chain iter test" << std::endl; - for (auto i : iter::chain(empty,vec1,arr1)) { - std::cout << i << std::endl; - } - std::cout<{1,2,3,4}, - std::array{{5,6,7,8}})) { - std::cout << i << '\n'; - } - } - -} diff --git a/tests/testchainfromiterable.cpp b/tests/testchainfromiterable.cpp deleted file mode 100644 index f4b6d599..00000000 --- a/tests/testchainfromiterable.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -#include -#include - -using iter::chain; - -int main() { - std::vector> matrix = { - {1, 2, 3}, - {4, 5}, - {6, 8, 9, 10, 11, 12} - }; - for (auto i : chain.from_iterable(matrix)) { - std::cout << i << '\n'; - } - - std::cout << "with temporary\n"; - for (auto i : chain.from_iterable(std::vector>{ - {1, 2, 3}, - {4, 5}, - {6, 8, 9, 10, 11, 12} - })) { - std::cout << i << '\n'; - } - - return 0; -} diff --git a/tests/testcombinations.cpp b/tests/testcombinations.cpp deleted file mode 100644 index 4dce1139..00000000 --- a/tests/testcombinations.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "samples.hpp" -#include -#include - -#include -#include -#include -#include - -using iter::combinations; -int main() { - itertest::DerefByValue dbv; - std::vector mv; - for (auto i : iter::range(3)) { - mv.emplace_back(i); - } - std::vector v = {1,2,3,4,5}; - - for (auto i : combinations(mv,2)) { - for (auto j : i ) std::cout << j << " "; - std::cout<{1,2,3,4,5}, 3)) { - for (auto j : i ) std::cout << j << " "; - std::cout< -#include - -#include -#include -#include -#include - -using iter::combinations_with_replacement; - -int main() { - std::vector mv; - for (auto i : iter::range(3)) { - mv.emplace_back(i); - } - - std::vector v = {1,2,3,}; - for (auto i : combinations_with_replacement(v,4)) { - for (auto j : i ) std::cout << j << " "; - std::cout<{1,2,3},4)) { - for (auto j : i ) std::cout << j << " "; - std::cout< - -#include -#include -#include -#include -#include - -using namespace iter; - -template -std::ostream & operator<<(std::ostream & out, const boost::optional& opt) { - if (opt) { - out << "Just " << *opt; - } else { - out << "Nothing"; - } - return out; -} -int main() { - { - std::vector vec1{1,2,3,4,5,6}; - std::vector vec2{1,2,3,4,5}; - std::vector strvec - {"his","name","was","robert","paulson","his","name","was","robert","paulson"}; - for (auto t : zip_longest(chain(vec1,vec2),strvec)) { - std::cout << std::get<0>(t) << " " - << std::get<1>(t) << std::endl; - } - } - - std::string str = "hello world"; - std::vector vec = {6, 9, 6, 9}; - for (auto p : enumerate(enumerate(str))) { (void)p; } - for (auto p : enumerate(zip(str, vec))) { (void)p; } - - std::cout << std::endl; - { - std::vector vec1{1,2,3,4,5,6}; - std::vector vec2{7,8,9,10}; - std::vector strvec - {"We're","done","when","I","say","we're","done"}; - for (auto t : zip(strvec,chain(slice(vec1,2,6),slice(vec2,1,4)))) { - std::cout << std::get<0>(t) << " " - << std::get<1>(t) << std::endl; - } - } - std::cout << std::endl; - { - std::vector vec1{1,2,3,4,5,6}; - std::vector vec2{7,8,9,10}; - for (auto s : sliding_window(chain(vec1,vec2),4)) { - for (auto i : s) std::cout << i << " "; - std::cout< vec1{1,2,3,4,5,6}; - std::vector vec2{7,8,9,10}; - for (auto s : grouper(chain(vec1,vec2),3)) { - for (auto i : s) std::cout << i << " "; - std::cout< const& c) - {return std::get<0>(c) >= std::get<1>(c);}, - prod_range)) { - std::cout << std::get<0>(ij) << "," << std::get<1>(ij) << std::endl; - } - return 0; -} diff --git a/tests/testcompress.cpp b/tests/testcompress.cpp deleted file mode 100644 index 5197f3e2..00000000 --- a/tests/testcompress.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#include -#include - -using iter::compress; -using iter::range; - -template -void testcase(std::vector data_vec, - std::vector sel_vec) -{ - - for (auto e : compress(data_vec, sel_vec)) { - std::cout << e << '\n'; - } -} - -int main(void) -{ - std::vector ivec{1, 2, 3, 4, 5, 6}; - std::vector bvec{true, false, true, false, true, false}; - std::cout << "Should print 1 3 5\n"; - testcase(ivec, bvec); - - std::vector bvec2{false, true, false, false, false, true}; - std::cout << "Should print 2 6\n"; - testcase(ivec, bvec2); - - std::vector bvec3{false, true}; - std::cout << "Should print 2\n"; - testcase(ivec, bvec3); - - std::cout << "Should print 0 2 4\n"; - for (auto i : compress(range(10), bvec)) { - std::cout << i << '\n'; - } - - std::cout << "Should print 0 2 4\n"; - for (auto i : compress({0,1,2,3,4,5}, bvec)) { - std::cout << i << '\n'; - } - - std::cout << "Should print 0 2 4\n"; - for (auto i : compress(range(10), {true, false, true, false, true})) { - std::cout << i << '\n'; - } - - std::cout << "Should print 0 2 4\n"; - for (auto i : compress({0, 1, 2, 3, 4, 5}, - {true, false, true, false, true})) - { - std::cout << i << '\n'; - } - - std::cout << "Should print 0 2 4\n"; - for (auto i : compress(std::vector{0, 1, 2, 3, 4, 5}, - std::vector{true, false, true, false, true})) - { - std::cout << i << '\n'; - } - - - - return 0; -} diff --git a/tests/testcount.cpp b/tests/testcount.cpp deleted file mode 100644 index 946d6841..00000000 --- a/tests/testcount.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include - -using iter::count; - -int main() { - for (auto i : count()) { - std::cout << i << '\n'; - if (i == 100) { - break; - } - } - - for (auto i : count(5.0, 0.5)){ - std::cout << i << '\n'; - if (i > 100) { - break; - } - } - - for (auto i : count(0, -1)) { - std::cout << i << '\n'; - if (i < -100) { - break; - } - } - - for (auto i : count()) { - std::cout << i << '\n'; - if (i > 10000) { - break; - } - } - - - return 0; -} diff --git a/tests/testcycle.cpp b/tests/testcycle.cpp deleted file mode 100644 index 138692cc..00000000 --- a/tests/testcycle.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include - -#include -#include - -using iter::cycle; -using iter::range; - -int main() { - std::vector vec = {2, 4, 6}; - - size_t count = 0; - for (auto i : cycle(vec)) { - std::cout << i << '\n'; - if (count == 100) { - break; - } - ++count; - } - - count = 0; - int array[] = {68, 69, 70}; - for (auto i : cycle(array)) { - std::cout << i << '\n'; - if (count == 20) { - break; - } - ++count; - } - - count = 0; - for (auto i : cycle({7, 8, 9})) { - std::cout << i << '\n'; - if (count == 20) { - break; - } - ++count; - } - - count = 0; - for (auto i : cycle(range(3))) { - std::cout << i << '\n'; - if (count == 20) { - break; - } - ++count; - } - - count = 0; - const std::string s("hello"); - for (auto c : cycle(s)) { - std::cout << c << '\n'; - if (count == 20) { - break; - } - ++count; - } - - count = 0; - for (auto i : std::vector{1,2,3,4,5}) { - std::cout << i << '\n'; - if (count == 20) { - break; - } - ++count; - } - - return 0; -} diff --git a/tests/testdropwhile.cpp b/tests/testdropwhile.cpp deleted file mode 100644 index 3140f81a..00000000 --- a/tests/testdropwhile.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -#include -#include -#include - -using iter::dropwhile; -using iter::range; - -int main() { - std::vector ivec{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4}; - for (auto& i : dropwhile([] (int i) {return i < 5;}, ivec)) { - std::cout << i << '\n'; - i = 69; - } - assert(ivec.at(0) == 1); - assert(ivec.at(4) == 69); - - for (auto i : dropwhile([] (int i) {return i < 5;}, range(10))) { - std::cout << i << '\n'; - } - - for (auto i : dropwhile([] (int i) {return i < 5;}, - {1, 2, 3, 4, 5, 6, 7, 8, 9})) { - std::cout << i << '\n'; - } - - for (auto i : dropwhile([] (int i) {return i < 5;}, - std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9})) { - std::cout << i << '\n'; - } - - return 0; -} diff --git a/tests/testenumerate.cpp b/tests/testenumerate.cpp deleted file mode 100644 index fcc1745c..00000000 --- a/tests/testenumerate.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include -#include -#include - -using iter::enumerate; -using iter::range; - -int main() { - std::cout << "const std::string\n"; - const std::string const_string("goodbye world"); - for (auto e : enumerate(const_string)) { - std::cout << e.index << ": " << e.element << std::endl; - } - - - std::vector vec; - for(int i = 0; i < 12; ++i) { - vec.push_back(i * i); - } - - - std::cout << "print vector element, set it to zero, then print it again\n"; - for (auto e : enumerate(vec)) { - std::cout << e.index << ": " << e.element << std::endl; - e.element = 0; - // tests to make sure vector can be edited - std::cout << e.index << ": " << e.element << std::endl; - } - - std::cout << "static array\n"; - int array[] = {1, 9, 8, 11}; - for (auto e : enumerate(array)) { - std::cout << e.index << ": " << e.element << '\n'; - } - - std::cout << "initializer list\n"; - for (auto e : enumerate({0, 1, 4, 9, 16, 25})) { - std::cout << e.index << "^2 = " << e.element << '\n'; - } - - std::cout << "range(10, 20, 2)\n"; - for (auto e : enumerate(range(10, 20, 2))) { - std::cout << e.index << ": " << e.element << '\n'; - } - - std::cout << "range(10, 20, 2)\n"; - for (auto e : enumerate(enumerate(range(10, 20, 2)))) { - std::cout << e.index << ": " << e.element.element << '\n'; - } - - std::cout << "vector temporary\n"; - for (auto e : enumerate(std::vector(5,2))) { - std::cout << e.index << ": " << e.element << '\n'; - } - - return 0; -} diff --git a/tests/testfilter.cpp b/tests/testfilter.cpp deleted file mode 100644 index e8af2aab..00000000 --- a/tests/testfilter.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -#include -#include - -using iter::filter; - -bool greater_than_four(int i) { - return i > 4; -} - -class LessThanValue { - private: - int compare_val; - - public: - LessThanValue() = delete; - LessThanValue(int v) : compare_val(v) { } - - bool operator() (int i) { - return i < this->compare_val; - } -}; - - -int main() { - std::vector vec{1, 5, 6, 7, 2, 3, 8, 3, 2, 1}; - - std::cout << "Greater than 4 (function pointer)\n"; - for (auto i : filter(greater_than_four, vec)) { - std::cout << i << '\n'; - } - - std::cout << "Less than 4 (lambda)\n"; - for (auto i : filter([] (const int i) { return i < 4; }, vec)) { - std::cout << i << '\n'; - } - - LessThanValue lv(4); - std::cout << "Less than 4 (callable object)\n"; - for (auto i : filter(lv, vec)) { - std::cout << i << '\n'; - } - - std::cout << "Nonzero ints filter(vec2)\n"; - std::vector vec2 {0, 1, 2, 0, 3, 0, 0, 0, 4, 5, 0}; - for (auto i : filter(vec2)) { - std::cout << i << '\n'; - } - - std::cout << "odd numbers in range(10) temp\n"; - for (auto i : filter([] (const int i) {return i % 2;}, iter::range(10))) { - std::cout << i << '\n'; - } - - std::cout << "range(-1, 2)\n"; - for (auto i : filter(iter::range(-1, 2))) { - std::cout << i << '\n'; - } - - - std::cout << "ever numbers in initializer_list\n"; - for (auto i : filter([] (const int i) {return i % 2 == 0;}, - {1, 2, 3, 4, 5, 6, 7})) - { - std::cout << i << '\n'; - } - - std::cout << "default in initialization_list\n"; - for (auto i : filter({-2, -1, 0, 0, 0, 1, 2})) { - std::cout << i << '\n'; - } - - std::cout << "ever numbers in vector temporary\n"; - for (auto i : filter([] (const int i) {return i % 2 == 0;}, - std::vector{1, 2, 3, 4, 5, 6, 7})) - { - std::cout << i << '\n'; - } - - return 0; -} diff --git a/tests/testfilterfalse.cpp b/tests/testfilterfalse.cpp deleted file mode 100644 index 9063d0bf..00000000 --- a/tests/testfilterfalse.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include -#include - -using iter::filterfalse; -using iter::range; - -bool greater_than_four(int i) { - return i > 4; -} - -class LessThanValue { - private: - int compare_val; - - public: - LessThanValue() = delete; - LessThanValue(int v) : compare_val(v) { } - - bool operator() (int i) const { - return i < this->compare_val; - } -}; - - -int main() { - std::vector vec{1, 5, 6, 7, 2, 3, 8, 3, 2, 1}; - - std::cout << "Greater than 4 (function pointer)\n"; - for (auto i : filterfalse(greater_than_four, vec)) { - std::cout << i << '\n'; - } - - std::cout << "Less than 4 (lambda)\n"; - for (auto i : filterfalse([] (const int i) { return i < 4; }, vec)) { - std::cout << i << '\n'; - } - - LessThanValue lv(4); - std::cout << "Less than 4 (callable object)\n"; - for (auto i : filterfalse(lv, vec)) { - std::cout << i << '\n'; - } - - std::cout << "zero ints filter(vec2)\n"; - std::vector vec2 {0, 1, 2, 0, 3, 0, 0, 0, 4, 5, 0}; - for (auto i : filterfalse(vec2)) { - std::cout << i << '\n'; - } - - std::cout << "Constness tests\n"; - const std::vector cvec(vec); - for (auto i : filterfalse(greater_than_four, cvec)) { - std::cout << i << '\n'; - } - - for (auto i : filterfalse([] (const int & i) { return i < 4; }, cvec)) { - std::cout << i << '\n'; - } - - - std::cout << "i%2 with range(10), should print even numbers\n"; - for (auto i : filterfalse([] (const int i) { return i % 2; }, range(10))) { - std::cout << i << '\n'; - } - - std::cout << "range(-1, 2)\n"; - for (auto i : filterfalse(range(-1, 2))) { - std::cout << i << '\n'; - } - - std::cout << "initializer_list\n"; - for (auto i : filterfalse([] (const int i) { return i % 2; }, - {10, 11, 12, 13, 14, 15, 16})) - { - std::cout << i << '\n'; - } - - std::cout << "initializer_list with default\n"; - for (auto i : filterfalse({-1, -2, 0, 0, 0, 0, 1, 2, 3})) { - std::cout << i << '\n'; - } - - std::cout << "vector temporary with default\n"; - for (auto i : filterfalse( - std::vector{-1, -2, 0, 0, 0, 0, 1, 2, 3})) { - std::cout << i << '\n'; - } - - return 0; -} diff --git a/tests/testgroupby.cpp b/tests/testgroupby.cpp deleted file mode 100644 index 9fc03ee3..00000000 --- a/tests/testgroupby.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include - -#include -#include -#include - -using iter::groupby; - - -int length(std::string s) -{ - return s.length(); -} - -int main() -{ - std::vector vec = { - "hi", "ab", "ho", - "abc", "def", - "abcde", "efghi" - }; - - for (auto gb : groupby(vec, &length)) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - for (auto gb : groupby(vec, [] (const std::string &s) {return s.length(); })) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - std::cout << "skipping length of 3\n"; - for (auto gb : groupby(vec, &length)) { - if (gb.first == 3) { - continue; - } - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - - std::vector ivec = {5, 5, 6, 6, 19, 19, 19, 19, 69, 0, 10, 10}; - for (auto gb : groupby(ivec)) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - for (auto gb : groupby("aabbccccdd", [] (const char c) {return c < 'c';})){ - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - for (auto gb : groupby({'a', 'a', 'b', 'b', 'c'})) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - for (auto gb : groupby({'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'}, - [] (const char c) {return c < 'c'; })) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - std::cout << "with vector temporary:\n"; - for (auto gb : groupby( - std::vector{'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'}, - [] (const char c) {return c < 'c'; })) { - std::cout << "key: " << gb.first << '\n'; - std::cout << "content: "; - for (auto s : gb.second) { - std::cout << s << " "; - } - std::cout << '\n'; - } - - - return 0; -} - - diff --git a/tests/testgrouper.cpp b/tests/testgrouper.cpp deleted file mode 100644 index b16ebc98..00000000 --- a/tests/testgrouper.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "grouper.hpp" -#include -#include -using iter::grouper; -int main() { - std::vector v {1,2,3,4,5,6,7,8,9}; - for (auto sec : grouper(v,4)) { - for (auto i : sec) { - std::cout << i << " "; - i.get() *= 2; - } - std::cout << '\n'; - } - - for (auto sec : grouper(std::vector{1,2,3,4,5,6,7,8,9}, 4)) { - for (auto i : sec) { - std::cout << i << " "; - i.get() *= 2; - } - std::cout << '\n'; - } - - for (auto sec : grouper(v,3)) { - for (auto i : sec) { - std::cout << i << " "; - } - std::cout << '\n'; - } - std::vector empty {}; - for (auto sec : grouper(empty,3)) { - std::cout << "Shouldn't print\n"; - for (auto i : sec) { - std::cout << i << " Shouldn't print\n"; - } - } - - int arr[] = {1,2,3,4,5,6,7}; - for (auto sec : grouper(arr, 2)) { - for (auto i : sec) { - std::cout << i << ' '; - } - std::cout << '\n'; - } - - for (auto sec : grouper({1,2,3,4,5,6,7}, 2)) { - for (auto i : sec) { - std::cout << i << ' '; - } - std::cout << '\n'; - } -} diff --git a/tests/testimap.cpp b/tests/testimap.cpp deleted file mode 100644 index 3d6f38ca..00000000 --- a/tests/testimap.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include -#include - -using iter::imap; - -int main() { - std::vector vec1 = {1, 2, 3, 4, 5, 6}; - std::vector vec2 = {10, 20, 30, 40, 50, 60}; - for (auto i : imap([] (int x, int y) { return x + y; }, vec1, vec2)) { - std::cout << i << '\n'; - } - - std::vector vec3 = {100, 200, 300, 400, 500, 600}; - for (auto i : imap([] (int a, int b, int c) { return a + b + c; }, - vec1, vec2, vec3)) { - std::cout << i << '\n'; - } - - for (auto i : imap([] (int i) {return i * i; }, vec1)) { - std::cout << i << '\n'; - } - - std::vector vec{1, 2, 3, 4, 5}; - for (auto i : imap([] (int x) {return x * x;}, vec)) { - std::cout << i << '\n'; - } - - std::vector vec4{1, 2, 3}; - for (auto i : imap([] (int a, int b) { return a + b; }, vec, vec4)) { - std::cout << i << '\n'; - } - - for (auto i : imap([] (const int x) { return x*x; }, iter::range(10))) { - std::cout << i << '\n'; - } - - for (auto i : imap([] (const int x) { return x*x; }, - std::vector{1,2,3,4,5})){ - std::cout << i << '\n'; - } - return 0; -} diff --git a/tests/testpermutations.cpp b/tests/testpermutations.cpp deleted file mode 100644 index a73a2a3b..00000000 --- a/tests/testpermutations.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "samples.hpp" - -#include -#include - -#include -#include -#include - -int main() { - using iter::permutations; - std::vector v = {1,2,3}; - for (auto vec : permutations(v)) { - for (auto i : vec) { - std::cout << i << " "; - } - std::cout << std::endl; - } - //try with string - std::string s = "aba"; - for (auto vec : permutations(s)) { - for (auto c : vec) { - std::cout << c << " "; - } - std::cout << std::endl; - } - s = "abc"; - for (auto vec : permutations(s)) { - for (auto c : vec) { - std::cout << c << " "; - } - std::cout << std::endl; - } - - std::cout << "init list\n"; - //std::next_permutation doesn't work on initializer_lists - for (auto vec : permutations({1,2,3,4})) { - for (auto c : vec) { - std::cout << c << " "; - } - std::cout << std::endl; - } - - std::cout << "with container of move-only objects\n"; - std::vector mv; - for (auto i : iter::range(3)) { - mv.emplace_back(i); - } - for (auto v : permutations(mv)) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - - std::cout << "with deref-by-value iterator\n"; - itertest::DerefByValue dbv; - for (auto v : permutations(dbv)) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } -} diff --git a/tests/testpowerset.cpp b/tests/testpowerset.cpp deleted file mode 100644 index 20ca0098..00000000 --- a/tests/testpowerset.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "samples.hpp" -#include -#include -#include -#include - -using iter::powerset; - -int main() { - std::vector vec {1,2,3,4,5,6,7,8,9}; - for (auto v : powerset(vec)) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - std::cout << "with temporary\n"; - for (auto v : powerset(std::vector{1,2,3})) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - std::cout << "with initializer_list\n"; - for (auto v : powerset({1,2,3})) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - - std::cout << "with container of move-only objects\n"; - std::vector mv; - for (auto i : iter::range(3)) { - mv.emplace_back(i); - } - for (auto v : powerset(mv)) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - - std::cout << "with deref-by-value iterator\n"; - itertest::DerefByValue dbv; - for (auto v : powerset(dbv)) { - for (auto i : v) std::cout << i << " "; - std::cout << std::endl; - } - - return 0; -} diff --git a/tests/testproduct.cpp b/tests/testproduct.cpp deleted file mode 100644 index 22d132ec..00000000 --- a/tests/testproduct.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "samples.hpp" - -#include -#include - -#include -#include -#include - -using iter::product; -int main() { - - std::vector mv; - for (auto i : iter::range(10)) { - mv.emplace_back(i); - } - std::vector empty{}; - std::vector v1{1,2,3}; - std::vector v2{7,8}; - std::vector v3{"the","cat"}; - std::vector v4{"hi","what","up","dude"}; - - for (auto t : product(v1, mv)) { - std::cout << std::get<0>(t) << ", " - << std::get<1>(t) << std::endl; - } - for (auto t : product(empty,v1)) { - std::cout << std::get<0>(t) << ", " - << std::get<1>(t) << std::endl; - } - for (auto t : product(v1,empty)) { - std::cout << std::get<0>(t) << ", " - << std::get<1>(t) << std::endl; - } - std::cout<(t) << ", " - << std::get<1>(t) << std::endl; - } - std::cout<(t) << ", " - << std::get<1>(t) << ", " - << std::get<2>(t) << ", " - << std::get<3>(t) << std::endl; - } - std::cout<(t) << std::endl; - } - std::cout<(t) << ", " - << std::get<1>(t) << std::endl; - } - std::cout << '\n'; - - for (auto t : product()) { t=t; } - - for (auto t : product(std::string{"hi"}, v1)) { - std::cout << std::get<0>(t) << ", " - << std::get<1>(t) << std::endl; - } - std::cout << '\n'; - - int arr[] = {1,2}; - for (auto t : product(std::string{"hi"}, arr)) { - std::cout << std::get<0>(t) << ", " - << std::get<1>(t) << std::endl; - } - std::cout << '\n'; - for (auto&& ij: iter::product(iter::range(10), iter::range(5))) { - std::cout << std::get<0>(ij) << "," << std::get<1>(ij) << std::endl; - } - - return 0; -} diff --git a/tests/testrange.cpp b/tests/testrange.cpp deleted file mode 100644 index 9404ae57..00000000 --- a/tests/testrange.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include - -#include - -using iter::range; - -int main() -{ - for (auto i : range(10)) { - std::cout << i << std::endl; - } - for (auto i : range(20, 30)) { - std::cout << i << std::endl; - } - for (auto i : range(50, 60, 2)) { - std::cout << i << std::endl; - } - - std::cout << "Negative Tests\n"; - for (auto i: range(-10, 0)) { - std::cout << i << std::endl; - } - - for (auto i : range(-10, 10, 2)) { - std::cout << i << std::endl; - } - - std::cout << "Tests where (stop - start)%step != 0" << std::endl; - for (auto i : range(1, 10, 2)) { - std::cout << i << std::endl; - } - - for (auto i : range(-1, -10, -2)) { - std::cout << i << std::endl; - } - - std::cout << "Tests with different types" << std::endl; - for(auto i : range(5.0, 10.0, 0.5)) { - std::cout << i << std::endl; - } - std::cout << "test unsigned" << std::endl; - std::cout << "empty range: " << std::endl; - size_t len = 0; - for(auto i : range(len)){ - std::cout << i << std::endl; - } - std::cout << "stop only" << std::endl; - len = 3; - for(auto i : range(len)){ - std::cout << i << std::endl; - } - std::cout << "start stop" << std::endl; - size_t start = 1; - for(auto i : range(start, len)){ - std::cout << i << std::endl; - } - - std::cout << "start stop skip" << std::endl; - len = 10; - size_t skip = 3; - for(auto i : range(start, len, skip)){ - std::cout << i << std::endl; - } - - - - // invalid ranges: - std::cout << "Should not print anything after this line until exception\n"; - for (auto i : range(-10, 0, -1)) { - std::cout << i << std::endl; - } - - for (auto i : range(0, 1, -1)) { - std::cout << i << std::endl; - } - - std::cout << "Should see exception now\n"; - for (auto i : range(0, 10, 0) ) { - std::cout << i << std::endl; - } - - return 0; -} diff --git a/tests/testrepeat.cpp b/tests/testrepeat.cpp deleted file mode 100644 index b91fba03..00000000 --- a/tests/testrepeat.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "repeat.hpp" -#include -#include -#include -#include -#include - -int main () { - int a = 10; - int i = 0; - for (auto num : iter::repeat(a)) {//goes infintely - std::cout << num << std::endl; - ++i; - if (i > 20) break; - } - std::cout<{new int{2}}, 2)) { - std::cout << *p << '\n'; - } - -} diff --git a/tests/testreversed.cpp b/tests/testreversed.cpp deleted file mode 100644 index c6d0ab46..00000000 --- a/tests/testreversed.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include - -#include -#include -#include -#include - -int main () { - std::vector a{1,2,3,4,5,6,7}; - std::vector b{"hey","how","are","you","doing"}; - std::cout << std::endl << "reversed range test" << std::endl << std::endl; - for (auto i : iter::reversed(a)) { - std::cout << i << std::endl; - } - std::cout<{1, 2, 3, 4, 5, 6, 7})) { - std::cout << i << '\n'; - } - - std::cout << "statically sized array\n"; - int arr[] = {1, 2, 3, 4, 5, 6, 7}; - for (auto i : iter::reversed(arr)) { - std::cout << i << '\n'; - } - - -} diff --git a/tests/testslice.cpp b/tests/testslice.cpp deleted file mode 100644 index eaf8e1ce..00000000 --- a/tests/testslice.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include - -#include -#include - -#include -#include - -int main() { - std::cout << std::endl << "Slice range test" << std::endl << std::endl; - std::vector a{0,1,2,3,4,5,6,7,8,9,10,11,12,13}; - std::vector b{"hey","how","are","you","doing"}; - - std::cout << "step out of slice\n"; - for (auto i : iter::slice(a, 1, 4, 5)) { - std::cout << i << '\n'; - } - std::cout << "end step out\n"; - - for (auto i : iter::slice(a,2)) { - std::cout << i << std::endl; - } - std::cout<{1, 2, 4, 8, 16, 32, 64, 128}, 2, 6)) { - std::cout << i << '\n'; - } - -} diff --git a/tests/testsliding_window.cpp b/tests/testsliding_window.cpp deleted file mode 100644 index 16708db7..00000000 --- a/tests/testsliding_window.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "sliding_window.hpp" - -#include -#include - -using iter::sliding_window; - -int main() { - std::vector v = {1,2,3,4,5,6,7,8,9}; - for (auto sec : sliding_window(v,4)) { - for (auto i : sec) { - std::cout << i << " "; - i.get() = 90; - } - std::cout << std::endl; - } - - std::cout << "with temporary\n"; - for (auto sec : sliding_window(std::vector{1,2,3,4,5,6,7,8,9}, 4)) { - for (auto i : sec) { - std::cout << i << " "; - i.get() = 90; - } - std::cout << std::endl; - } - - std::cout << "with init list\n"; - for (auto sec : sliding_window({1,2,3,4,5,6,7,8,9}, 4)) { - for (auto i : sec) { - std::cout << i << " "; - } - std::cout << std::endl; - } - - std::cout << "with window_size > length\n"; - for (auto sec : sliding_window({1,2,3}, 10)) { - for (auto i : sec) { - std::cout << i << " "; - } - std::cout << std::endl; - } - - std::cout << "with static array\n"; - int arr[] = {1,2,3,4,5,6,7,8,9}; - for (auto sec : sliding_window(arr, 4)) { - for (auto i : sec) { - std::cout << i << " "; - } - std::cout << std::endl; - } - - return 0; -} diff --git a/tests/testsorted.cpp b/tests/testsorted.cpp deleted file mode 100644 index aed57d32..00000000 --- a/tests/testsorted.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include -#include -#include - -using iter::sorted; - -int main() -{ - std::vector vec = {19, 45, 32, 10, 0, 90, 15, 1, 7, 5, 6, 69}; - for (auto i : sorted(vec)) { - std::cout << i << '\n'; - } - - const std::vector cvec(vec); - for (auto i : sorted(cvec)) { - std::cout << i << '\n'; - } - - std::cout << "Sort by first character only\n"; - std::vector svec = {"hello", "everyone", "thanks", "for", - "having", "me", "here", "today"}; - for (auto s : sorted(svec, - [] (const std::string & s1, const std::string & s2) { - return s1[0] < s2[0]; })) { - std::cout << s << '\n'; - } - - - for (auto i : sorted( - std::vector{19, 45, 32, 10, 0, 90, 15, 1, 7, 5, 6, 69})) { - std::cout << i << '\n'; - } - return 0; -} diff --git a/tests/teststarmap.cpp b/tests/teststarmap.cpp deleted file mode 100644 index f85bd40d..00000000 --- a/tests/teststarmap.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using iter::starmap; - -double f(double d, int i) { - return d * i; -} - -std::string g(const std::string& s, int i, double d) { - std::stringstream ss; - ss << s << ' ' << i << ' ' << d; - return ss.str(); -} - -void test_normal() { - std::cout << "vector>\n"; - std::vector> v1 = {{1.0, 2}, {3.2, 42}, {6.9, 7}}; - for (auto&& i : starmap(f, v1)) { - std::cout << i << '\n'; - } - std::cout << '\n'; - - std::cout << "list\n"; - { - using T = std::tuple; - std::list li = - {T{"hey", 42, 6.9}, T{"there", 3, 4.0}, T{"yall", 5, 3.1}}; - for (auto&& s : starmap(g, li)) { - std::cout << s << '\n'; - } - } - std::cout << '\n'; -} - -struct Callable { - int operator()(int a, int b, int c) { - return a + b + c; - } - - int operator()(int a) { - return a; - } -}; - -void test_tuple_of_tuples() { - auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); - Callable c; - std::cout << "tuple, tuple>\n"; - for (auto&& i : starmap(c, tup)) { - std::cout << i << '\n'; - } - - auto tup2 = std::make_tuple(std::array{{15, 100, 2000}}, - std::make_tuple(16)); - std::cout << "tuple, tuple>\n"; - for (auto&& i : starmap(c, tup2)) { - std::cout << i << '\n'; - } - std::cout << '\n'; - - std::cout << "pair, tuple>\n"; - auto p = std::make_pair(std::array{{15, 100, 2000}}, - std::make_tuple(16)); - for (auto&& i : starmap(c, p)) { - std::cout << i << '\n'; - } - std::cout << '\n'; -} - -int main() { - test_normal(); - test_tuple_of_tuples(); - -} diff --git a/tests/testtakewhile.cpp b/tests/testtakewhile.cpp deleted file mode 100644 index bec3aeae..00000000 --- a/tests/testtakewhile.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -#include -#include - -using iter::takewhile; -using iter::range; - -int main() { - std::vector ivec{1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1}; - for (auto i : takewhile([] (int i) {return i < 5;}, ivec)) { - std::cout << i << '\n'; - } - - for (auto i : takewhile([] (int i) {return i < 5;}, range(10))) { - std::cout << i << '\n'; - } - - for (auto i : takewhile([] (int i) {return i < 5;}, - {1, 2, 3, 4, 5, 6, 7, 8, 9})) { - std::cout << i << '\n'; - } - - std::cout << "with temporary\n"; - for (auto i : takewhile([] (int i) {return i < 5;}, - std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9})) { - std::cout << i << '\n'; - } - - return 0; -} diff --git a/tests/testunique_everseen.cpp b/tests/testunique_everseen.cpp deleted file mode 100644 index 015adb7d..00000000 --- a/tests/testunique_everseen.cpp +++ /dev/null @@ -1,41 +0,0 @@ - -#include -#include - -#include -using iter::unique_everseen; - -int main() { - { - //should work same as justseen here - std::vector v {1,1,1,2,2,3,4,4,5,6,7,8,8,8,8,9,9}; - for (auto i : unique_everseen(v)) { - std::cout << i << " "; - }std::cout << std::endl; - } - { - std::vector v {1,2,3,4,3,2,1,5,6,7,7,8,9,8,9,6}; - for (auto i : unique_everseen(v)) { - std::cout << i << " "; - }std::cout << std::endl; - } - - for (auto i : unique_everseen( - std::vector{1,2,1,3,4,3,2,1,5,6,7,7,8,9,8,9,6})) { - std::cout << i << " "; - } - std::cout << std::endl; - - int arr[] = {1,2,1,3,4,3,2,1,5,6,7,7,8,9,8,9,6}; - for (auto i : unique_everseen(arr)) { - std::cout << i << ' '; - } - std::cout << '\n'; - - for (auto i : unique_everseen({1,2,1,3,4,3,2,1,5,6,7,7,8,9,8,9,6})) { - std::cout << i << ' '; - } - std::cout << '\n'; - - return 0; -} diff --git a/tests/testunique_justseen.cpp b/tests/testunique_justseen.cpp deleted file mode 100644 index 8f454b6d..00000000 --- a/tests/testunique_justseen.cpp +++ /dev/null @@ -1,35 +0,0 @@ - -#include -#include - -#include -using iter::unique_justseen; - -int main() { - std::vector v {1,1,1,2,2,4,4,5,6,7,8,8,8,8,9,9}; - for (auto i : unique_justseen(v)) { - std::cout << i << " "; - } - std::cout << '\n'; - - std::cout << "with temporary\n"; - for (auto i : unique_justseen(std::vector{1,1,1,2,3,3})) { - std::cout << i << " "; - } - std::cout << '\n'; - - std::cout << "with init list\n"; - for (auto i : unique_justseen({1,1,1,2,3,3})) { - std::cout << i << " "; - } - std::cout << '\n'; - - std::cout << "with static array\n"; - int arr[] = {1, 1, 2, 3, 3, 3, 4}; - for (auto i : unique_justseen(arr)) { - std::cout << i << " "; - } - std::cout << '\n'; - - return 0; -} diff --git a/tests/testzip.cpp b/tests/testzip.cpp deleted file mode 100644 index 76a95fd7..00000000 --- a/tests/testzip.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include - -using iter::zip; - -int main() { - //Ryan's test - { - for (auto t : zip()) { t=t; } - - std::vector ivec{1, 4, 9, 16, 25, 36}; - std::vector svec{"hello", "good day", "goodbye"}; - - constexpr int magic_value = 69; - for (auto e : zip(ivec, svec)) { - auto &i = std::get<0>(e); - std::cout << i << std::endl; - i = magic_value; - std::cout << std::get<1>(e) << std::endl; - } - assert(ivec.at(0) == magic_value); - for (auto e : zip(ivec, svec)) { - std::cout << std::get<0>(e) << std::endl; - std::cout << std::get<1>(e) << std::endl; - } - - for (auto e : zip(std::vector{5,6,7})) { - std::cout << std::get<0>(e) << std::endl; - } - for (auto e : zip(std::vector{5,6,7}, std::array{{1,2}})){ - std::cout << std::get<0>(e) << std::endl; - std::cout << std::get<1>(e) << std::endl; - } - - for (auto e : zip(iter::range(10), iter::range(10, 20))) { - std::cout << std::get<0>(e) << '\n'; - std::cout << std::get<1>(e) << '\n'; - } - - int arr[] = {1,2,3,3,4}; - for (auto e : zip(iter::range(10), arr)) { - std::cout << std::get<0>(e) << '\n'; - std::cout << std::get<1>(e) << '\n'; - } - - } - //Aaron's test - { - std::array i{{1,2,3,4}}; - std::vector f{1.2,1.4,12.3,4.5,9.9}; - std::vector s{"i","like","apples","alot","dude"}; - std::array d{{1.2,1.2,1.2,1.2,1.2}}; - std::cout << std::endl << "Variadic template zip iterator" << std::endl; - for (auto e : iter::zip(i,f,s,d)) { - std::cout << std::get<0>(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) << " " - << std::get<3>(e) << std::endl; - std::get<1>(e)=2.2f; //modify the float array - } - std::cout<(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) << " " - << std::get<3>(e) << std::endl; - } - std::cout << std::endl << "Try some weird range differences" << std::endl; - std::vector empty{}; - for (auto e : iter::zip(empty,f,s,d)) { - std::cout << std::get<0>(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) << " " - << std::get<3>(e) << std::endl; - } - std::cout<(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) << " " - << std::get<3>(e) << std::endl; - }//both should print nothing - std::cout<(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) << " " - << std::get<3>(e) << std::endl; - } - std::cout< constvector{1.1,2.2,3.3,4.4}; - for (auto e : zip( - iter::chain(std::vector{5,6}, - std::array{{1,2}}), - std::initializer_list{ - "asdfas","aaron","ryan","apple","juice"}, - std::initializer_list{1, 2, 3, 4}, - constvector)) - { - - std::cout << std::get<0>(e) << " " - << std::get<1>(e) << " " - << std::get<2>(e) - << '\n'; - } - } - - - return 0; -} - diff --git a/tests/testzip_longest.cpp b/tests/testzip_longest.cpp deleted file mode 100644 index 63dc8fd0..00000000 --- a/tests/testzip_longest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -using iter::zip_longest; - -template -std::ostream & operator<<(std::ostream & out, const boost::optional& opt) { - if (opt) { - out << "Just " << *opt; - } else { - out << "Nothing"; - } - return out; -} - -int main() { - //Ryan's test - { - std::vector ivec{1, 4, 9, 16, 25, 36}; - std::vector svec{"hello", "good day", "goodbye"}; - - for (auto e : zip_longest(ivec, svec)) { - std::cout << std::get<0>(e) << std::endl; - std::cout << std::get<1>(e) << std::endl; - } - - for (auto e : zip_longest("helloworld", - std::vector{1,2,3})) { - std::cout << std::get<0>(e) << std::endl; - std::cout << std::get<1>(e) << std::endl; - } - } - //Aaron's test - { - std::array i{{1,2,3,4}}; - std::vector f{1.2,1.4,12.3,4.5,9.9}; - std::vector s{"i","like","apples","alot","dude"}; - std::array d{{1.2,1.2,1.2,1.2,1.2}}; - std::cout << std::endl << "Variadic template zip_longest" << std::endl; - for (auto e : iter::zip_longest(i,f,s,d)) { - std::cout << std::get<0>(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - *std::get<1>(e)=2.2f; //modify the float array - } - std::cout<<"modified array" <(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - } - std::cout << std::endl << "Try some weird range differences" << std::endl; - std::vector empty{}; - for (auto e : iter::zip_longest(empty,f,s,d)) { - std::cout << std::get<0>(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - } - std::cout<(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - } - std::cout<(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - } - std::cout<{1,2,3,4,5,6}, - std::initializer_list{1.1,2.2,3.3,4.4}, - std::initializer_list{1.1,2.2,3.3,4.4}, - std::array{{1,2,3}})) { - std::cout << std::get<0>(e) << ' ' - << std::get<1>(e) << ' ' - << std::get<2>(e) << ' ' - << std::get<3>(e) << std::endl; - } - std::cout< Date: Wed, 20 May 2015 00:52:44 -0700 Subject: [PATCH 073/596] moves test_starmap into test/ --- {catchtest => test}/test_starmap.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {catchtest => test}/test_starmap.cpp (100%) diff --git a/catchtest/test_starmap.cpp b/test/test_starmap.cpp similarity index 100% rename from catchtest/test_starmap.cpp rename to test/test_starmap.cpp From d6a0b4911987db540942ee79fbf7daf15c211907 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 01:17:06 -0700 Subject: [PATCH 074/596] adds starmap_examples.cpp file --- examples/starmap_examples.cpp | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 examples/starmap_examples.cpp diff --git a/examples/starmap_examples.cpp b/examples/starmap_examples.cpp new file mode 100644 index 00000000..9797756c --- /dev/null +++ b/examples/starmap_examples.cpp @@ -0,0 +1,40 @@ +#include + +#include +#include +#include +#include + +// Since this is an example file I'm dumping a bunch of using declarations +// here, in real code I use using declarations very sparingly +using std::pair; +using std::tuple; +using std::vector; +using std::make_pair; +using std::make_tuple; + +struct Callable { + int operator()(int i) const { return i; } + int operator()(int i, char c) const { return i + c; } + int operator()(unsigned int u, int i, char c) const { return i + c + u; } +}; + +int main() { + // the function will be called with the tuple-like object unpacked + // using std::get. This means an iterable of tuples, arrays, pairs, or + // whatever works with std::get + vector> v = {{2, 3}, {5, 2}, {3, 4}}; // {base, exponent} + for (auto&& i : iter::starmap([](int b, int e){ return b * e; }, v)) { + std::cout << i << '\n'; + } + + // Alternatively if an object has multiple call operators, a tuple-like + // object of tuple-like objects + auto t = make_tuple( + make_tuple(5), // first form + make_pair(3, 'c'), // second form + make_tuple(1u, 1, '1')); // third form + for (auto&& i : iter::starmap(Callable{}, t)) { + std::cout << i << '\n'; + } +} From e4e2d21bcad1d561d602af5612f6228ed89161f8 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 01:17:58 -0700 Subject: [PATCH 075/596] builds starmap_examples --- examples/SConstruct | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/SConstruct b/examples/SConstruct index 41acb956..3a9bfbb4 100644 --- a/examples/SConstruct +++ b/examples/SConstruct @@ -4,7 +4,7 @@ env = Environment( ENV = {'PATH' : os.environ['PATH']}, CXX='c++', CXXFLAGS= ['-g', '-Wall', '-Wextra', - '-pedantic', '-std=c++11', + '-pedantic', '-std=c++14', '-fdiagnostics-color=always', '-I/usr/local/include'], CPPPATH='..', @@ -34,6 +34,7 @@ progs = Split( slice sliding_window sorted + starmap takewhile unique_justseen unique_everseen From 8fa94f7452cd28adc0007886630b3eae8174dec4 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 10:55:54 -0700 Subject: [PATCH 076/596] adds reverse iter aliases --- iterbase.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/iterbase.hpp b/iterbase.hpp index 9f6177e4..5e66cd7f 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -44,7 +44,7 @@ namespace iter { // iterator_type is the type of C's iterator template using reverse_iterator_type = - decltype(std::declval().rbegin()); + decltype(std::rbegin(std::declval())); // iterator_deref is the type obtained by dereferencing an iterator // to an object of type C @@ -52,6 +52,10 @@ namespace iter { using reverse_iterator_deref = decltype(*std::declval&>()); + template + using reverse_iterator_traits_deref = + std::remove_reference_t>; + template struct is_random_access_iter : std::false_type { }; From 128806ee5a5d26ca94a5f0538afbaaded59bee65 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 10:56:06 -0700 Subject: [PATCH 077/596] uses std::rbegin and rend, removes specialization Instead of using .rbegin() and .rend(), uses non-member std::rbegin() and std::rend() to get the iterators. This also means (like replacing .begin() with std::begin() forever ago) that Reverser can handle arrays. This commit removes the array specialization. --- reversed.hpp | 83 +++++----------------------------------------------- 1 file changed, 7 insertions(+), 76 deletions(-) diff --git a/reversed.hpp b/reversed.hpp index 0e03b6c1..8fdaa96e 100644 --- a/reversed.hpp +++ b/reversed.hpp @@ -13,13 +13,12 @@ namespace iter { template Reverser reversed(Container&&); - template class Reverser { private: Container container; friend Reverser reversed(Container&&); - + Reverser(Container&& in_container) : container(std::forward(in_container)) { } @@ -27,20 +26,20 @@ namespace iter { public: class Iterator : public std::iterator< std::input_iterator_tag, - iterator_traits_deref> + reverse_iterator_traits_deref> { private: reverse_iterator_type sub_iter; public: - Iterator (reverse_iterator_type&& iter) + Iterator(reverse_iterator_type&& iter) : sub_iter{std::move(iter)} - { } + { } reverse_iterator_deref operator*() { return *this->sub_iter; } - Iterator& operator++() { + Iterator& operator++() { ++this->sub_iter; return *this; } @@ -61,11 +60,11 @@ namespace iter { }; Iterator begin() { - return {this->container.rbegin()}; + return {std::rbegin(this->container)}; } Iterator end() { - return {this->container.rend()}; + return {std::rend(this->container)}; } }; @@ -74,74 +73,6 @@ namespace iter { Reverser reversed(Container&& container) { return {std::forward(container)}; } - - // - // specialization for statically allocated arrays - // - template - Reverser reversed(T (&)[N]); - - template - class Reverser { - private: - T *array; - friend Reverser reversed(T (&)[N]); - - // Value constructor for use only in the reversed function - Reverser(T *in_array) - : array{in_array} - { } - - public: - Reverser(const Reverser&) = default; - class Iterator : public std::iterator - { - private: - T *sub_iter; - public: - Iterator (T *iter) - : sub_iter{iter} - { } - - iterator_deref operator*() { - return *(this->sub_iter - 1); - } - - Iterator& operator++() { - --this->sub_iter; - return *this; - } - - Iterator operator++(int) { - auto ret = *this; - ++*this; - return ret; - } - - bool operator!=(const Iterator& other) const { - return this->sub_iter != other.sub_iter; - } - - bool operator==(const Iterator& other) const { - return !(*this != other); - } - }; - - Iterator begin() { - return {this->array + N}; - } - - Iterator end() { - return {this->array}; - } - - }; - - template - Reverser reversed(T (&array)[N]) { - return {array}; - } - } #endif From 684dcf6c4c5fe9e3f8ab4ea7b626c256693f07c9 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 11:10:42 -0700 Subject: [PATCH 078/596] moves reverse_iterator aliases into reversed.hpp They're only used in reversed, they don't need to be in iterbase --- iterbase.hpp | 16 ---------------- reversed.hpp | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 5e66cd7f..7bf65d69 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -36,26 +36,10 @@ namespace iter { using const_iterator_deref = decltype(*std::declval&>()); - template using iterator_traits_deref = std::remove_reference_t>; - // iterator_type is the type of C's iterator - template - using reverse_iterator_type = - decltype(std::rbegin(std::declval())); - - // iterator_deref is the type obtained by dereferencing an iterator - // to an object of type C - template - using reverse_iterator_deref = - decltype(*std::declval&>()); - - template - using reverse_iterator_traits_deref = - std::remove_reference_t>; - template struct is_random_access_iter : std::false_type { }; diff --git a/reversed.hpp b/reversed.hpp index 8fdaa96e..e270c971 100644 --- a/reversed.hpp +++ b/reversed.hpp @@ -23,19 +23,28 @@ namespace iter { : container(std::forward(in_container)) { } + using reverse_iterator_type = + decltype(std::rbegin(std::declval())); + + using reverse_iterator_deref = + decltype(*std::declval()); + + using reverse_iterator_traits_deref = + std::remove_reference_t; + public: class Iterator : public std::iterator< std::input_iterator_tag, - reverse_iterator_traits_deref> + reverse_iterator_traits_deref> { private: - reverse_iterator_type sub_iter; + reverse_iterator_type sub_iter; public: - Iterator(reverse_iterator_type&& iter) + Iterator(reverse_iterator_type&& iter) : sub_iter{std::move(iter)} { } - reverse_iterator_deref operator*() { + reverse_iterator_deref operator*() { return *this->sub_iter; } From b4cec8441bb74fe6aaad93db8d2a68a8a87244e3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Wed, 20 May 2015 11:19:06 -0700 Subject: [PATCH 079/596] conditionally declares BasicIterable::rbegin --- test/helpers.hpp | 18 +++++------------- test/test_reversed.cpp | 5 ++++- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/test/helpers.hpp b/test/helpers.hpp index 7c36ca89..c0db7fe7 100644 --- a/test/helpers.hpp +++ b/test/helpers.hpp @@ -110,19 +110,6 @@ class BasicIterable { BasicIterable& operator=(const BasicIterable&) = delete; BasicIterable(const BasicIterable&) = delete; -#if 0 - BasicIterable(const BasicIterable& other) - : data{new T[other.size()]}, - size{other.size} - { - for (auto it = this->begin(), o_it = other.begin(); - o_it != other.end(); - ++it, ++o_it) { - *it = *o_it; - } - } -#endif - BasicIterable(BasicIterable&& other) : data{other.data}, @@ -170,6 +157,11 @@ class BasicIterable { Iterator end() { return {this->data + this->size}; } + +#ifdef DECLARE_REVERSE_ITERATOR + Iterator rbegin(); + Iterator rend(); +#endif // ifdef DECLARE_REVERSE_ITERATOR }; using iter::void_t; diff --git a/test/test_reversed.cpp b/test/test_reversed.cpp index 389badd0..6736b1a7 100644 --- a/test/test_reversed.cpp +++ b/test/test_reversed.cpp @@ -5,9 +5,12 @@ #include #include -#include "helpers.hpp" #include "catch.hpp" +#define DECLARE_REVERSE_ITERATOR +#include "helpers.hpp" +#undef DECLARE_REVERSE_ITERATOR + using iter::reversed; using Vec = const std::vector; From 91201db3b6901ed75b1dc576cb05d4f7613615ed Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 21 May 2015 15:27:05 -0700 Subject: [PATCH 080/596] removes trailing space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bb7e56a..48d9dcfc 100644 --- a/README.md +++ b/README.md @@ -368,7 +368,7 @@ zip Takes an arbitrary number of ranges of different types and efficiently iterates over them in parallel (so an iterator to each container is incremented simultaneously). When you dereference an iterator to "zipped" range you get a -tuple of the elements the iterators were holding. +tuple of the elements the iterators were holding. Example usage: ```c++ From 1209101060265fc848fab3a3fa681584e4d8b5a9 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Tue, 26 May 2015 12:24:39 -0700 Subject: [PATCH 081/596] replaces "naked new" in chain with make_unique --- chain.hpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/chain.hpp b/chain.hpp index 5b0a1086..bc4fd097 100644 --- a/chain.hpp +++ b/chain.hpp @@ -60,7 +60,7 @@ class Chained { constexpr static std::array derefers{{ get_and_deref...}}; - + constexpr static std::array incrementers{{ get_and_increment...}}; @@ -68,7 +68,7 @@ class Chained { get_and_check_not_equal...}}; - using TraitsValue = + using TraitsValue = iterator_traits_deref>; private: TupType tup; @@ -188,8 +188,8 @@ constexpr std::array< static std::unique_ptr clone_sub_pointer( const SubIter* sub_iter) { - return std::unique_ptr{ sub_iter ? - new SubIter{*sub_iter} : nullptr}; + return sub_iter ? + std::make_unique(*sub_iter) : nullptr; } bool sub_iters_differ(const Iterator& other) const { @@ -211,9 +211,11 @@ constexpr std::array< : top_level_iter{std::move(top_iter)}, top_level_end{std::move(top_end)}, sub_iter_p{!(top_iter != top_end) ? // iter == end ? - nullptr : new SubIter{std::begin(*top_iter)}}, + nullptr : + std::make_unique(std::begin(*top_iter))}, sub_end_p{!(top_iter != top_end) ? // iter == end ? - nullptr : new SubIter{std::end(*top_iter)}} + nullptr : + std::make_unique(std::end(*top_iter))} { } Iterator(const Iterator& other) @@ -245,13 +247,15 @@ constexpr std::array< if (!(*this->sub_iter_p != *this->sub_end_p)) { ++this->top_level_iter; if (this->top_level_iter != this->top_level_end) { - sub_iter_p.reset( - new SubIter{std::begin(*this->top_level_iter)}); - sub_end_p.reset( - new SubIter{std::end(*this->top_level_iter)}); + sub_iter_p = + std::make_unique( + std::begin(*this->top_level_iter)); + sub_end_p = + std::make_unique( + std::end(*this->top_level_iter)); } else { - sub_iter_p.reset(nullptr); - sub_end_p.reset(nullptr); + sub_iter_p.reset(); + sub_end_p.reset(); } } return *this; From 1d458f3aabca03224d3d1fae7acd8e8e2b26190b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Tue, 26 May 2015 12:29:54 -0700 Subject: [PATCH 082/596] removes "naked new"s in powerset using make_shared --- powerset.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/powerset.hpp b/powerset.hpp index 555be582..d3743cc4 100644 --- a/powerset.hpp +++ b/powerset.hpp @@ -39,7 +39,8 @@ namespace iter { Iterator(Container& in_container, std::size_t sz) : container_p{&in_container}, set_size{sz}, - comb{new CombinatorType(combinations(in_container, sz))}, + comb{std::make_shared( + combinations(in_container, sz))}, comb_iter{std::begin(*comb)}, comb_end{std::end(*comb)} { } @@ -48,8 +49,9 @@ namespace iter { ++this->comb_iter; if (this->comb_iter == this->comb_end) { ++this->set_size; - this->comb.reset(new CombinatorType(combinations( - *this->container_p, this->set_size))); + this->comb = std::make_shared( + combinations( + *this->container_p, this->set_size)); this->comb_iter = std::begin(*this->comb); this->comb_end = std::end(*this->comb); } From 7413ddb05d7105f8f4290c492c83df0d8905e688 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Tue, 26 May 2015 13:44:56 -0700 Subject: [PATCH 083/596] replaces "naked new"s in iterbase with make_unique --- iterbase.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/iterbase.hpp b/iterbase.hpp index 7bf65d69..16679a4f 100644 --- a/iterbase.hpp +++ b/iterbase.hpp @@ -200,12 +200,13 @@ namespace iter { DerefHolder() = default; DerefHolder(const DerefHolder& other) - : item_p{other.item_p ? new TPlain(*other.item_p) : nullptr} + : item_p{other.item_p ? + std::make_unique(*other.item_p) : nullptr} { } DerefHolder& operator=(const DerefHolder& other) { - this->item_p.reset(other.item_p - ? new TPlain(*other.item_p) : nullptr); + this->item_p = other.item_p ? + std::make_unique(*other.item_p) : nullptr; return *this; } @@ -224,7 +225,7 @@ namespace iter { } void reset(T&& item) { - item_p.reset(new TPlain(std::move(item))); + item_p = std::make_unique(std::move(item)); } explicit operator bool() const { @@ -236,8 +237,7 @@ namespace iter { // Specialization for when T is an lvalue ref. Keep this in mind // wherever a T appears. template - class DerefHolder::value>::type> + class DerefHolder::value>> { private: static_assert(std::is_lvalue_reference::value, From 93177acc9bd7b32b779601106eb394534d09b0c5 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:42:37 -0700 Subject: [PATCH 084/596] tests chain.from_iterable arrow --- test/test_chain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_chain.cpp b/test/test_chain.cpp index 46319d33..b4cf0836 100644 --- a/test/test_chain.cpp +++ b/test/test_chain.cpp @@ -186,6 +186,12 @@ TEST_CASE("chain.from_iterable: postfix ++", "[chain.from_iterable]") { REQUIRE( *it == 'n' ); } +TEST_CASE("chain.from_iterable: operator->","[chain.from_iterable]") { + std::vector> sv{{"a", "ab"}, {"abc"}}; + auto ch = chain.from_iterable(sv); + auto it = std::begin(ch); + REQUIRE( it->size() == 1 ); +} TEST_CASE("chain.from_iterable: moves rvalues and binds ref to lvalues", "[chain.from_iterable]") { From 4eb45a6f8c36ee6b082ac9aa02fd9b476c7b042f Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:42:48 -0700 Subject: [PATCH 085/596] implements chain.from_iterable arrow --- chain.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/chain.hpp b/chain.hpp index 2556fecc..3fb097a5 100644 --- a/chain.hpp +++ b/chain.hpp @@ -255,6 +255,10 @@ class iter::impl::ChainedFromIterable { iterator_deref> operator*() { return **this->sub_iter_p; } + + iterator_arrow> operator->() { + return apply_arrow(*this->sub_iter_p); + } }; Iterator begin() { From afbe4ffccc2bb08c31f1597e0c70984e320f04c6 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:48:30 -0700 Subject: [PATCH 086/596] puts back in chain operator-> --- chain.hpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/chain.hpp b/chain.hpp index 3fb097a5..b50e520f 100644 --- a/chain.hpp +++ b/chain.hpp @@ -41,12 +41,18 @@ class iter::impl::Chained { using IterTupType = iterator_tuple_type; using DerefType = iterator_deref>; + using ArrowType = iterator_arrow>; template static DerefType get_and_deref(IterTupType& iters) { return *std::get(iters); } + template + static ArrowType get_and_arrow(IterTupType& iters) { + return apply_arrow(std::get(iters)); + } + template static void get_and_increment(IterTupType& iters) { ++std::get(iters); @@ -59,12 +65,16 @@ class iter::impl::Chained { } using DerefFunc = DerefType (*)(IterTupType&); + using ArrowFunc = ArrowType (*)(IterTupType&); using IncFunc = void (*)(IterTupType&); using NeqFunc = bool (*)(const IterTupType&, const IterTupType&); constexpr static std::array derefers{ {get_and_deref...}}; + constexpr static std::array arrowers{ + {get_and_arrow...}}; + constexpr static std::array incrementers{ {get_and_increment...}}; @@ -77,7 +87,6 @@ class iter::impl::Chained { TupType tup; public: - Chained(Chained&&) = default; Chained(TupType&& t) : tup(std::move(t)) {} class Iterator : public std::iterator { @@ -103,6 +112,10 @@ class iter::impl::Chained { return derefers[this->index](this->iters); } + decltype(auto) operator -> () { + return arrowers[this->index](this->iters); + } + Iterator& operator++() { incrementers[this->index](this->iters); this->check_for_end_and_adjust(); @@ -141,6 +154,10 @@ template constexpr std::array::DerefFunc, sizeof...(Is)> iter::impl::Chained::derefers; +template +constexpr std::array::ArrowFunc, + sizeof...(Is)> iter::impl::Chained::arrowers; + template constexpr std::array::IncFunc, sizeof...(Is)> iter::impl::Chained::incrementers; From 3fc699523184273335b94801330bf21c7fbe91fd Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:50:15 -0700 Subject: [PATCH 087/596] adds back zip and zip_longest iter-> --- zip.hpp | 5 ++ zip_longest.hpp | 201 ++++++++++++++++++++++++------------------------ 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/zip.hpp b/zip.hpp index 1771ed32..569ea6ee 100644 --- a/zip.hpp +++ b/zip.hpp @@ -33,6 +33,7 @@ class iter::impl::Zipped { Zipped(TupleType&& in_containers) : containers(std::move(in_containers)) {} public: + Zipped(Zipped&&) = default; class Iterator : public std::iterator { private: iterator_tuple_type iters; @@ -67,6 +68,10 @@ class iter::impl::Zipped { ZipIterDeref operator*() { return ZipIterDeref{(*std::get(this->iters))...}; } + + auto operator -> () -> ArrowProxy { + return {**this}; + } }; Iterator begin() { diff --git a/zip_longest.hpp b/zip_longest.hpp index 98b20ec4..800261b7 100644 --- a/zip_longest.hpp +++ b/zip_longest.hpp @@ -1,124 +1,121 @@ #ifndef ITER_ZIP_LONGEST_HPP_ #define ITER_ZIP_LONGEST_HPP_ -#include "iterbase.hpp" +#include "internal/iterbase.hpp" #include #include #include #include - namespace iter { - + namespace impl { template class ZippedLongest; template - ZippedLongest - zip_longest_impl(TupleType&&, std::index_sequence); + ZippedLongest zip_longest_impl( + TupleType&&, std::index_sequence); + } - template - class ZippedLongest { - private: - TupleType containers; - friend ZippedLongest zip_longest_impl( - TupleType&&, std::index_sequence); - - template - using OptType = boost::optional>>; - - using ZipIterDeref = std::tuple...>; - - ZippedLongest(TupleType&& in_containers) - : containers(std::move(in_containers)) - { } - public: - class Iterator - : public std::iterator - { - private: - iterator_tuple_type iters; - iterator_tuple_type ends; - - public: - Iterator(iterator_tuple_type&& in_iters, - iterator_tuple_type&& in_ends) - : iters(std::move(in_iters)), - ends(std::move(in_ends)) - { } - - Iterator& operator++() { - // increment every iterator that's not already at - // the end - absorb( - ((std::get(this->iters) != - std::get(this->ends)) ? - (++std::get(this->iters), 0) : 0)...); - return *this; - } - - Iterator operator++(int) { - auto ret = *this; - ++*this; - return ret; - } - - bool operator!=(const Iterator& other) const { - if (sizeof...(Is) == 0) return false; - - bool results[] = { false, - (std::get(this->iters) != - std::get(other.iters))... - }; - return std::any_of( - std::begin(results), std::end(results), - [](bool b){ return b; } ); - } - - bool operator==(const Iterator& other) const { - return !(*this != other); - } - - ZipIterDeref operator*() { - return ZipIterDeref{ - ((std::get(this->iters) != - std::get(this->ends)) - ? OptType{*std::get(this->iters)} - : OptType{})...}; - } - }; - - Iterator begin() { - return { - iterator_tuple_type{ - std::begin(std::get(this->containers))...}, - iterator_tuple_type{ - std::end(std::get(this->containers))...}}; - } - - Iterator end() { - return { - iterator_tuple_type{ - std::end(std::get(this->containers))...}, - iterator_tuple_type{ - std::end(std::get(this->containers))...}}; - } -}; + template + auto zip_longest(Containers&&... containers); +} - template - ZippedLongest zip_longest_impl( - TupleType&& in_containers, std::index_sequence) { - return {std::move(in_containers)}; +template +class iter::impl::ZippedLongest { + private: + TupleType containers; + friend ZippedLongest zip_longest_impl( + TupleType&&, std::index_sequence); + + template + using OptType = + boost::optional>>; + + using ZipIterDeref = std::tuple...>; + + ZippedLongest(TupleType&& in_containers) + : containers(std::move(in_containers)) {} + + public: + ZippedLongest(ZippedLongest&&) = default; + class Iterator : public std::iterator { + private: + iterator_tuple_type iters; + iterator_tuple_type ends; + + public: + Iterator(iterator_tuple_type&& in_iters, + iterator_tuple_type&& in_ends) + : iters(std::move(in_iters)), ends(std::move(in_ends)) {} + + Iterator& operator++() { + // increment every iterator that's not already at + // the end + absorb(((std::get(this->iters) != std::get(this->ends)) + ? (++std::get(this->iters), 0) + : 0)...); + return *this; } - template - auto zip_longest(Containers&&... containers) { - return zip_longest_impl(std::tuple{ - std::forward(containers)...}, - std::index_sequence_for{}); + Iterator operator++(int) { + auto ret = *this; + ++*this; + return ret; + } + + bool operator!=(const Iterator& other) const { + if (sizeof...(Is) == 0) return false; + + bool results[] = { + false, (std::get(this->iters) != std::get(other.iters))...}; + return std::any_of( + std::begin(results), std::end(results), [](bool b) { return b; }); } + + bool operator==(const Iterator& other) const { + return !(*this != other); + } + + ZipIterDeref operator*() { + return ZipIterDeref{ + ((std::get(this->iters) != std::get(this->ends)) + ? OptType{*std::get(this->iters)} + : OptType{})...}; + } + + auto operator -> () -> ArrowProxy { + return {**this}; + } + }; + + Iterator begin() { + return {iterator_tuple_type{ + std::begin(std::get(this->containers))...}, + iterator_tuple_type{ + std::end(std::get(this->containers))...}}; + } + + Iterator end() { + return {iterator_tuple_type{ + std::end(std::get(this->containers))...}, + iterator_tuple_type{ + std::end(std::get(this->containers))...}}; + } +}; + +template +iter::impl::ZippedLongest iter::impl::zip_longest_impl( + TupleType&& in_containers, std::index_sequence) { + return {std::move(in_containers)}; +} + +template +auto iter::zip_longest(Containers&&... containers) { + return impl::zip_longest_impl( + std::tuple{std::forward(containers)...}, + std::index_sequence_for{}); } #endif From 7fbb8b5cde31079d6c242f74af0a24d2265a4958 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:51:03 -0700 Subject: [PATCH 088/596] make Chained ctor private --- chain.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain.hpp b/chain.hpp index b50e520f..cc7c4d5c 100644 --- a/chain.hpp +++ b/chain.hpp @@ -84,10 +84,10 @@ class iter::impl::Chained { using TraitsValue = iterator_traits_deref>; private: + Chained(TupType&& t) : tup(std::move(t)) {} TupType tup; public: - Chained(TupType&& t) : tup(std::move(t)) {} class Iterator : public std::iterator { private: From af2a8b1922216886373f6f57de1261faed20986a Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 27 Aug 2015 22:52:00 -0700 Subject: [PATCH 089/596] makes Chained move-only --- chain.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/chain.hpp b/chain.hpp index cc7c4d5c..59369982 100644 --- a/chain.hpp +++ b/chain.hpp @@ -88,6 +88,7 @@ class iter::impl::Chained { TupType tup; public: + Chained(Chained&&) = default; class Iterator : public std::iterator { private: From 93c032eeaeda416d43e5b5b396200e9ff7c014a3 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 7 Sep 2015 12:01:48 -0700 Subject: [PATCH 090/596] adds dummy operator()() to ArrowHelper --- internal/iterbase.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/iterbase.hpp b/internal/iterbase.hpp index f9295170..c215d003 100644 --- a/internal/iterbase.hpp +++ b/internal/iterbase.hpp @@ -54,6 +54,7 @@ namespace iter { template struct ArrowHelper { using type = void; + void operator()(T&) const noexcept { } }; template From ec84a613c4d08e5214fbcad8b9c24fe92f22c2f0 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 27 Mar 2016 20:16:07 -0700 Subject: [PATCH 091/596] Removes development status notes from README --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 7cadd713..dd55604e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,5 @@ -CPPItertools C++14 development Branch +CPPItertools ============ - -**NOTE**: this branch is for refining and moving forward with the C++14 -standard. It will be merged into master when compiler and library -support for the standard approaches completion in common compilers. -Specifically I'm considering clang and gcc, along with libstdc++ -and libc++ - Range-based for loop add-ons inspired by the Python builtins and itertools library. Like itertools and the Python3 builtins, this library uses lazy evaluation wherever possible. From 7a872f9e3c37401bb98c0b44a56934381914770e Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 27 Mar 2016 20:38:54 -0700 Subject: [PATCH 092/596] uses callable struct instead of functions --- enumerate.hpp | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/enumerate.hpp b/enumerate.hpp index 715eb7b0..f104b6eb 100644 --- a/enumerate.hpp +++ b/enumerate.hpp @@ -13,14 +13,8 @@ namespace iter { namespace impl { template class Enumerable; + struct EnumerateFn; } - - template - impl::Enumerable enumerate(Container&&, std::size_t = 0); - - template - impl::Enumerable> enumerate( - std::initializer_list, std::size_t = 0); } template @@ -29,12 +23,7 @@ class iter::impl::Enumerable { Container container; const std::size_t start; - // The only thing allowed to directly instantiate an Enumerable is - // the enumerate function - friend Enumerable iter::enumerate(Container&&, std::size_t); - template - friend Enumerable> iter::enumerate( - std::initializer_list, std::size_t); + friend struct EnumerateFn; // for IterYield using BasePair = std::pair>; @@ -105,16 +94,22 @@ class iter::impl::Enumerable { } }; -template -iter::impl::Enumerable iter::enumerate( - Container&& container, std::size_t start) { - return {std::forward(container), start}; -} +struct iter::impl::EnumerateFn { + template + Enumerable operator()( + Container&& container, std::size_t start=0) const { + return {std::forward(container), start}; + } -template -iter::impl::Enumerable> iter::enumerate( - std::initializer_list il, std::size_t start) { - return {std::move(il), start}; + template + Enumerable> operator()( + std::initializer_list il, std::size_t start=0) const { + return {std::move(il), start}; + } +}; + +namespace iter { +constexpr impl::EnumerateFn enumerate; } #endif From fa2eb57bf8142b9a94c86d70a3597e6b6b42aec7 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 1 Apr 2016 19:53:20 -0700 Subject: [PATCH 093/596] Replaces filter() functions with FilterFn class --- filter.hpp | 82 ++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 45 deletions(-) diff --git a/filter.hpp b/filter.hpp index e899b80b..041b73c5 100644 --- a/filter.hpp +++ b/filter.hpp @@ -11,14 +11,9 @@ namespace iter { namespace impl { template class Filtered; - } - - template - impl::Filtered filter(FilterFunc, Container&&); - template - impl::Filtered> filter( - FilterFunc, std::initializer_list); + class FilterFn; + } } template @@ -27,12 +22,7 @@ class iter::impl::Filtered { Container container; FilterFunc filter_func; - // The filter function is the only thing allowed to create a Filtered - friend Filtered iter::filter(FilterFunc, Container&&); - - template - friend Filtered> iter::filter( - FF, std::initializer_list); + friend class FilterFn; // Value constructor for use only in the filter function Filtered(FilterFunc in_filter_func, Container&& in_container) @@ -117,46 +107,48 @@ class iter::impl::Filtered { } }; -template -iter::impl::Filtered iter::filter( - FilterFunc filter_func, Container&& container) { - return {filter_func, std::forward(container)}; -} - -template -iter::impl::Filtered> iter::filter( - FilterFunc filter_func, std::initializer_list il) { - return {filter_func, std::move(il)}; -} - -namespace iter { - namespace detail { +class iter::impl::FilterFn { + public: + template + iter::impl::Filtered operator()( + FilterFunc filter_func, Container&& container) const { + return {std::move(filter_func), std::forward(container)}; + } - template - bool boolean_cast(const T& t) { - return bool(t); - } + template + iter::impl::Filtered> operator()( + FilterFunc filter_func, std::initializer_list il) const { + return {std::move(filter_func), std::move(il)}; + } - template - class BoolTester { - public: - bool operator()(const impl::iterator_deref item) const { - return bool(item); - } - }; + template >> + auto operator()(Container&& container) const { + return (*this)(BoolTester{}, std::forward(container)); } - template - auto filter(Container&& container) { - return filter( - detail::BoolTester(), std::forward(container)); + template + auto operator()(std::initializer_list il) const { + return (*this)(BoolTester>{}, std::move(il)); } + private: template - auto filter(std::initializer_list il) { - return filter( - detail::BoolTester>(), std::move(il)); + bool boolean_cast(const T& t) { + return bool(t); } + + template + class BoolTester { + public: + bool operator()(const impl::iterator_deref item) const { + return bool(item); + } + }; +}; + +namespace iter { + constexpr impl::FilterFn filter{}; } #endif From 6bde3578abc84a071bcca85156fe1b7d48d4e5a4 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 1 Apr 2016 19:56:21 -0700 Subject: [PATCH 094/596] tests filter with predicate and pipe --- test/test_filter.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test_filter.cpp b/test/test_filter.cpp index c6dc58ec..6e391245 100644 --- a/test/test_filter.cpp +++ b/test/test_filter.cpp @@ -127,6 +127,15 @@ TEST_CASE("filter: doesn't move or copy elements of iterable", "[filter]") { } } +TEST_CASE("filter: works with pipe", "[filter]") { + Vec ns = {1, 2, 5, 6, 3, 1, 7, -1, 5}; + Vec vc = {1, 2, 3, 1, -1}; + + auto f = ns | filter(LessThanValue{5}); + Vec v(std::begin(f), std::end(f)); + REQUIRE(v == vc); +} + TEST_CASE("filter: iterator meets requirements", "[filter]") { std::string s{}; auto c = filter([] { return true; }, s); From 6f53bda39893a29942f2fecbb7612c38fb8cbff6 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 1 Apr 2016 19:56:36 -0700 Subject: [PATCH 095/596] supports seq | filter(predicate) --- filter.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/filter.hpp b/filter.hpp index 041b73c5..fa943bf4 100644 --- a/filter.hpp +++ b/filter.hpp @@ -132,6 +132,22 @@ class iter::impl::FilterFn { return (*this)(BoolTester>{}, std::move(il)); } + template + struct FilterFnPartial : Pipeable> { + FilterFnPartial(FilterFunc f) : fun(std::move(f)) {} + template + auto operator()(Container&& container) const { + return FilterFn{}(fun, std::forward(container)); + } + private: + FilterFunc fun; + }; + + template >> + FilterFnPartial operator()(FilterFunc filter_func) const { + return {filter_func}; + } + private: template bool boolean_cast(const T& t) { From b33570172d49fe896baecc20b76ac14a9a75683f Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 1 Apr 2016 19:58:39 -0700 Subject: [PATCH 096/596] supports seq | filter without predicate --- filter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filter.hpp b/filter.hpp index fa943bf4..6ea9c0f8 100644 --- a/filter.hpp +++ b/filter.hpp @@ -107,7 +107,7 @@ class iter::impl::Filtered { } }; -class iter::impl::FilterFn { +class iter::impl::FilterFn : public iter::impl::Pipeable { public: template iter::impl::Filtered operator()( From 06c528d1e941e3c70b61327f405b191ae7a86cc8 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Fri, 1 Apr 2016 19:59:03 -0700 Subject: [PATCH 097/596] tests filter with pipe and no predicate --- test/test_filter.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_filter.cpp b/test/test_filter.cpp index 6e391245..cc68f616 100644 --- a/test/test_filter.cpp +++ b/test/test_filter.cpp @@ -136,6 +136,16 @@ TEST_CASE("filter: works with pipe", "[filter]") { REQUIRE(v == vc); } +TEST_CASE("filter: using identity and pipe", "[filter]") { + Vec ns{0, 1, 2, 0, 3, 0, 0, 0, 4, 5, 0}; + auto f = ns | filter; + Vec v(std::begin(f), std::end(f)); + + Vec vc = {1, 2, 3, 4, 5}; + REQUIRE(v == vc); +} + + TEST_CASE("filter: iterator meets requirements", "[filter]") { std::string s{}; auto c = filter([] { return true; }, s); From 55d272ffdee8a8af84884d63b87f72c3534fd792 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 18:30:10 -0700 Subject: [PATCH 098/596] supports seq | enumerate --- enumerate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enumerate.hpp b/enumerate.hpp index f104b6eb..1c4fb666 100644 --- a/enumerate.hpp +++ b/enumerate.hpp @@ -94,7 +94,7 @@ class iter::impl::Enumerable { } }; -struct iter::impl::EnumerateFn { +struct iter::impl::EnumerateFn : iter::impl::Pipeable { template Enumerable operator()( Container&& container, std::size_t start=0) const { From 2be398391594b47ea5868ed713dba88f1e5e12fd Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 18:31:22 -0700 Subject: [PATCH 099/596] adds IsIterable trait and Pipeable helper I should've done these last few commits in a different order. IsIterable is true if T is an iterable (it can be passed to std::begin()). Pipeable is a helper to allow the sequence to be passed after the pipe. seq | iter::fun vs iter::fun(seq) --- internal/iterbase.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/iterbase.hpp b/internal/iterbase.hpp index 20d0fc39..afa9d0fd 100644 --- a/internal/iterbase.hpp +++ b/internal/iterbase.hpp @@ -50,6 +50,16 @@ namespace iter { using iterator_traits_deref = std::remove_reference_t>; + template + struct IsIterable : std::false_type {}; + + // Assuming that if a type works with std::begin, it is an iterable. + template + struct IsIterable>> : std::true_type{}; + + template + constexpr bool is_iterable = IsIterable::value; + namespace detail { template struct ArrowHelper { @@ -315,6 +325,18 @@ namespace iter { return this->item_p != nullptr; } }; + + // allows f(x) to be 'called' as x | f + // let the record show I dislike adding yet another syntactical mess to + // this clown car of a language. + template + struct Pipeable { + template + friend decltype(auto) operator|(T&& x, const Pipeable& p) { + return static_cast(p)(std::forward(x)); + } + }; + } } From 60d201da11bdd86b87628613b5a780215be13365 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 18:35:00 -0700 Subject: [PATCH 100/596] tests that enumerate works with pipe --- test/test_enumerate.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/test_enumerate.cpp b/test/test_enumerate.cpp index 778cce39..38b3a90a 100644 --- a/test/test_enumerate.cpp +++ b/test/test_enumerate.cpp @@ -137,6 +137,15 @@ TEST_CASE("enumerate: iterator meets requirements", "[enumerate]") { REQUIRE(itertest::IsIterator::value); } +TEST_CASE("enumerate: works with pipe", "[enumerate]") { + constexpr char str[] = {'a', 'b', 'c'}; + auto e = str | enumerate; + Vec v(std::begin(e), std::end(e)); + Vec vc{{0, 'a'}, {1, 'b'}, {2, 'c'}}; + + REQUIRE(v == vc); +} + template using ImpT = decltype(enumerate(std::declval())); TEST_CASE("enumerate: has correct ctor and assign ops", "[enumerate]") { From a4e454f9229955c640585aa8f4117fc6a6c5cefa Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 18:59:06 -0700 Subject: [PATCH 101/596] formatting --- test/test_chain.cpp | 10 ++-- test/test_imap.cpp | 8 +-- test/test_sorted.cpp | 6 +- test/test_starmap.cpp | 132 +++++++++++++++++++++--------------------- 4 files changed, 77 insertions(+), 79 deletions(-) diff --git a/test/test_chain.cpp b/test/test_chain.cpp index 8594e73a..7630270b 100644 --- a/test/test_chain.cpp +++ b/test/test_chain.cpp @@ -194,11 +194,11 @@ TEST_CASE("chain.from_iterable: postfix ++", "[chain.from_iterable]") { REQUIRE(*it == 'n'); } -TEST_CASE("chain.from_iterable: operator->","[chain.from_iterable]") { - std::vector> sv{{"a", "ab"}, {"abc"}}; - auto ch = chain.from_iterable(sv); - auto it = std::begin(ch); - REQUIRE( it->size() == 1 ); +TEST_CASE("chain.from_iterable: operator->", "[chain.from_iterable]") { + std::vector> sv{{"a", "ab"}, {"abc"}}; + auto ch = chain.from_iterable(sv); + auto it = std::begin(ch); + REQUIRE(it->size() == 1); } TEST_CASE("chain.from_iterable: moves rvalues and binds ref to lvalues", diff --git a/test/test_imap.cpp b/test/test_imap.cpp index 9a19cd87..f150d3aa 100644 --- a/test/test_imap.cpp +++ b/test/test_imap.cpp @@ -42,10 +42,10 @@ TEST_CASE("imap: works with lambda, callable, and function", "[imap]") { } SECTION("with callable") { - auto im = imap(PlusOner{}, ns); - Vec v(std::begin(im), std::end(im)); - Vec vc = {11, 21, 31}; - REQUIRE( v == vc ); + auto im = imap(PlusOner{}, ns); + Vec v(std::begin(im), std::end(im)); + Vec vc = {11, 21, 31}; + REQUIRE(v == vc); } SECTION("with function") { diff --git a/test/test_sorted.cpp b/test/test_sorted.cpp index cc477f84..f6c902ba 100644 --- a/test/test_sorted.cpp +++ b/test/test_sorted.cpp @@ -181,7 +181,7 @@ TEST_CASE("sorted: has correct ctor and assign ops", "[sorted]") { } TEST_CASE("sorted: iterator meets requirements", "[sorted]") { - Vec v; - auto r = sorted(v); - REQUIRE( itertest::IsIterator::value ); + Vec v; + auto r = sorted(v); + REQUIRE(itertest::IsIterator::value); } diff --git a/test/test_starmap.cpp b/test/test_starmap.cpp index 994f96b7..751d3d4e 100644 --- a/test/test_starmap.cpp +++ b/test/test_starmap.cpp @@ -12,100 +12,98 @@ using iter::starmap; namespace { - long f(long d, int i) { - return d * i; + long f(long d, int i) { + return d * i; + } + + std::string g(const std::string& s, int i, char c) { + std::stringstream ss; + ss << s << ' ' << i << ' ' << c; + return ss.str(); + } + + struct Callable { + int operator()(int a, int b, int c) { + return a + b + c; } - std::string g(const std::string& s, int i, char c) { - std::stringstream ss; - ss << s << ' ' << i << ' ' << c; - return ss.str(); + int operator()(int a) { + return a; } - - struct Callable { - int operator()(int a, int b, int c) { - return a + b + c; - } - - int operator()(int a) { - return a; - } - }; + }; } TEST_CASE("starmap: works with function pointer and lambda", "[starmap]") { - using Vec = const std::vector; - const std::vector> v1 = - {{1l, 2}, {3l, 11}, {6l, 7}}; - Vec vc = {2l, 33l, 42l}; - - SECTION("with function") { - auto sm = starmap(f, v1); - Vec v(std::begin(sm), std::end(sm)); - REQUIRE( v == vc ); - } + using Vec = const std::vector; + const std::vector> v1 = {{1l, 2}, {3l, 11}, {6l, 7}}; + Vec vc = {2l, 33l, 42l}; - SECTION("with lambda") { - auto sm = starmap([](long a, int b) { return a * b; }, v1); - Vec v(std::begin(sm), std::end(sm)); - REQUIRE( v == vc ); - } + SECTION("with function") { + auto sm = starmap(f, v1); + Vec v(std::begin(sm), std::end(sm)); + REQUIRE(v == vc); + } + + SECTION("with lambda") { + auto sm = starmap([](long a, int b) { return a * b; }, v1); + Vec v(std::begin(sm), std::end(sm)); + REQUIRE(v == vc); + } } TEST_CASE("starmap: list of tuples", "[starmap]") { - using Vec = const std::vector; - using T = std::tuple; - std::list li = - {T{"hey", 42, 'a'}, T{"there", 3, 'b'}, T{"yall", 5, 'c'}}; + using Vec = const std::vector; + using T = std::tuple; + std::list li = {T{"hey", 42, 'a'}, T{"there", 3, 'b'}, T{"yall", 5, 'c'}}; - auto sm = starmap(g, li); - Vec v(std::begin(sm), std::end(sm)); - Vec vc = {"hey 42 a", "there 3 b", "yall 5 c"}; + auto sm = starmap(g, li); + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {"hey 42 a", "there 3 b", "yall 5 c"}; - REQUIRE( v == vc ); + REQUIRE(v == vc); } TEST_CASE("starmap: tuple of tuples", "[starmap]") { - using Vec = const std::vector; - auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); - auto sm = starmap(Callable{}, tup); - Vec v(std::begin(sm), std::end(sm)); - Vec vc = {89, 7}; + using Vec = const std::vector; + auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7)); + auto sm = starmap(Callable{}, tup); + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {89, 7}; - REQUIRE( v == vc ); + REQUIRE(v == vc); } TEST_CASE("starmap: tuple of pairs", "[starmap]") { - using Vec = const std::vector; - auto p = std::make_pair(std::array{{15, 100, 2000}}, - std::make_tuple(16)); - Callable c; - auto sm = starmap(c, p); + using Vec = const std::vector; + auto p = + std::make_pair(std::array{{15, 100, 2000}}, std::make_tuple(16)); + Callable c; + auto sm = starmap(c, p); - Vec v(std::begin(sm), std::end(sm)); - Vec vc = {2115, 16}; + Vec v(std::begin(sm), std::end(sm)); + Vec vc = {2115, 16}; - REQUIRE( v == vc ); + REQUIRE(v == vc); } TEST_CASE("starmap: moves rvalues, binds to lvalues", "[starmap]") { - itertest::BasicIterable> bi{}; - starmap(Callable{}, bi); - REQUIRE_FALSE( bi.was_moved_from() ); - starmap(Callable{}, std::move(bi)); - REQUIRE( bi.was_moved_from() ); + itertest::BasicIterable> bi{}; + starmap(Callable{}, bi); + REQUIRE_FALSE(bi.was_moved_from()); + starmap(Callable{}, std::move(bi)); + REQUIRE(bi.was_moved_from()); } TEST_CASE("starmap: iterator meets requirements", "[starmap]") { - std::string s{}; - const std::vector> v1; - auto sm = starmap([](long a, int b) { return a * b; }, v1); - REQUIRE( itertest::IsIterator::value ); + std::string s{}; + const std::vector> v1; + auto sm = starmap([](long a, int b) { return a * b; }, v1); + REQUIRE(itertest::IsIterator::value); } -TEST_CASE("starmap: tuple of tuples iterator meets requirements", - "[starmap]") { - auto tup = std::make_tuple(std::make_tuple(10, 19, 60),std::make_tuple(7)); - auto sm = starmap(Callable{}, tup); - REQUIRE( itertest::IsIterator::value ); +TEST_CASE( + "starmap: tuple of tuples iterator meets requirements", "[starmap]") { + auto tup = std::make_tuple(std::make_tuple(10, 19, 60), std::make_tuple(7)); + auto sm = starmap(Callable{}, tup); + REQUIRE(itertest::IsIterator::value); } From 060632ec27056960b0866f533514efaf40fcf521 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 18:59:23 -0700 Subject: [PATCH 102/596] Make general use currier for passing first arg --- internal/iterbase.hpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/internal/iterbase.hpp b/internal/iterbase.hpp index afa9d0fd..c109c477 100644 --- a/internal/iterbase.hpp +++ b/internal/iterbase.hpp @@ -50,12 +50,12 @@ namespace iter { using iterator_traits_deref = std::remove_reference_t>; - template + template struct IsIterable : std::false_type {}; // Assuming that if a type works with std::begin, it is an iterable. template - struct IsIterable>> : std::true_type{}; + struct IsIterable>> : std::true_type {}; template constexpr bool is_iterable = IsIterable::value; @@ -209,7 +209,6 @@ namespace iter { using iterator_tuple_type = decltype(detail::iterator_tuple_type_helper(std::declval())); - // Given a tuple template argument, evaluates to a tuple of // what the iterators for the template argument's contained types // dereference to @@ -230,7 +229,7 @@ namespace iter { decltype(auto) call_with_tuple_impl( Func&& mf, TupleType&& tup, std::index_sequence) { return mf(std::forward>>(std::get(tup))...); + std::remove_reference_t>>(std::get(tup))...); } } @@ -329,14 +328,33 @@ namespace iter { // allows f(x) to be 'called' as x | f // let the record show I dislike adding yet another syntactical mess to // this clown car of a language. - template + template struct Pipeable { - template - friend decltype(auto) operator|(T&& x, const Pipeable& p) { - return static_cast(p)(std::forward(x)); + template + friend decltype(auto) operator|(T&& x, const Pipeable& p) { + return static_cast(p)(std::forward(x)); + } + }; + + // T is whatever is being held for later use + template + struct FnPartial : Pipeable> { + ItTool tool_fun; + mutable T t; + FnPartial(ItTool in_tool, T in_t) + : tool_fun(std::move(in_tool)), t(std::move(in_t)) {} + template + auto operator()(Container&& container) const { + return tool_fun(t, std::forward(container)); } }; +#if 0 + template + struct PipeableAndBindFirst : Pipeable { + + }; +#endif } } From d5b68aa5a76818bf007f100beace81602dc375b9 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 19:00:04 -0700 Subject: [PATCH 103/596] formatting --- test/test_filter.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/test_filter.cpp b/test/test_filter.cpp index cc68f616..63b8e068 100644 --- a/test/test_filter.cpp +++ b/test/test_filter.cpp @@ -73,12 +73,12 @@ TEST_CASE("filter: using identity", "[filter]") { TEST_CASE("filter: skips null pointers", "[filter]") { int a = 1; int b = 2; - const std::vector ns = {0, &a, nullptr, nullptr, &b, nullptr}; + const std::vector ns = {0, &a, nullptr, nullptr, &b, nullptr}; auto f = filter(ns); - const std::vector v(std::begin(f), std::end(f)); - const std::vector vc = {&a, &b}; - REQUIRE( v == vc ); + const std::vector v(std::begin(f), std::end(f)); + const std::vector vc = {&a, &b}; + REQUIRE(v == vc); } TEST_CASE("filter: binds to lvalues, moves rvales", "[filter]") { @@ -145,7 +145,6 @@ TEST_CASE("filter: using identity and pipe", "[filter]") { REQUIRE(v == vc); } - TEST_CASE("filter: iterator meets requirements", "[filter]") { std::string s{}; auto c = filter([] { return true; }, s); From 1c1843e247119ffcc8a09436fa0257dc7a0cd45f Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 19:00:09 -0700 Subject: [PATCH 104/596] uses general FnPartial --- filter.hpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/filter.hpp b/filter.hpp index 6ea9c0f8..31da8842 100644 --- a/filter.hpp +++ b/filter.hpp @@ -132,20 +132,10 @@ class iter::impl::FilterFn : public iter::impl::Pipeable { return (*this)(BoolTester>{}, std::move(il)); } - template - struct FilterFnPartial : Pipeable> { - FilterFnPartial(FilterFunc f) : fun(std::move(f)) {} - template - auto operator()(Container&& container) const { - return FilterFn{}(fun, std::forward(container)); - } - private: - FilterFunc fun; - }; - - template >> - FilterFnPartial operator()(FilterFunc filter_func) const { - return {filter_func}; + template >> + FnPartial operator()(FilterFunc filter_func) const { + return {*this, std::move(filter_func)}; } private: From 632d45131ac78b62357eb05cc0d996626de9e25b Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 19:55:47 -0700 Subject: [PATCH 105/596] minor FnPartial improvements --- internal/iterbase.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/internal/iterbase.hpp b/internal/iterbase.hpp index c109c477..64eae3e4 100644 --- a/internal/iterbase.hpp +++ b/internal/iterbase.hpp @@ -340,21 +340,23 @@ namespace iter { template struct FnPartial : Pipeable> { ItTool tool_fun; - mutable T t; - FnPartial(ItTool in_tool, T in_t) - : tool_fun(std::move(in_tool)), t(std::move(in_t)) {} + mutable T stored_arg; + constexpr FnPartial(ItTool in_tool, T in_t) + : tool_fun(in_tool), stored_arg(in_t) {} + template auto operator()(Container&& container) const { - return tool_fun(t, std::forward(container)); + return tool_fun(stored_arg, std::forward(container)); } }; -#if 0 template struct PipeableAndBindFirst : Pipeable { - + template >> + FnPartial operator()(Func func) const { + return {static_cast(*this), std::move(func)}; + } }; -#endif } } From e83e6a68e2b0c22ab03f8de6e1a7763720662691 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Sun, 3 Apr 2016 19:56:08 -0700 Subject: [PATCH 106/596] uses base class partial overload --- filter.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/filter.hpp b/filter.hpp index 31da8842..79e8d810 100644 --- a/filter.hpp +++ b/filter.hpp @@ -107,7 +107,7 @@ class iter::impl::Filtered { } }; -class iter::impl::FilterFn : public iter::impl::Pipeable { +class iter::impl::FilterFn : public PipeableAndBindFirst { public: template iter::impl::Filtered operator()( @@ -131,12 +131,7 @@ class iter::impl::FilterFn : public iter::impl::Pipeable { auto operator()(std::initializer_list il) const { return (*this)(BoolTester>{}, std::move(il)); } - - template >> - FnPartial operator()(FilterFunc filter_func) const { - return {*this, std::move(filter_func)}; - } + using PipeableAndBindFirst::operator(); private: template From c708b40579b49bdf05b1c3921af79463e1f3d442 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Mon, 4 Apr 2016 22:36:07 -0700 Subject: [PATCH 107/596] Removes extra "class" in friend declarations. --- chain.hpp | 4 ++-- enumerate.hpp | 2 +- filter.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chain.hpp b/chain.hpp index 66fd0f91..470ca4e3 100644 --- a/chain.hpp +++ b/chain.hpp @@ -28,7 +28,7 @@ namespace iter { template class iter::impl::Chained { private: - friend class ChainMaker; + friend ChainMaker; static_assert(std::tuple_size>::value == sizeof...(Is), "tuple size != sizeof Is"); @@ -171,7 +171,7 @@ template class iter::impl::ChainedFromIterable { private: Container container; - friend class ChainMaker; + friend ChainMaker; ChainedFromIterable(Container&& in_container) : container(std::forward(in_container)) {} diff --git a/enumerate.hpp b/enumerate.hpp index 1c4fb666..f85c8e21 100644 --- a/enumerate.hpp +++ b/enumerate.hpp @@ -23,7 +23,7 @@ class iter::impl::Enumerable { Container container; const std::size_t start; - friend struct EnumerateFn; + friend EnumerateFn; // for IterYield using BasePair = std::pair>; diff --git a/filter.hpp b/filter.hpp index 79e8d810..b2da5994 100644 --- a/filter.hpp +++ b/filter.hpp @@ -22,7 +22,7 @@ class iter::impl::Filtered { Container container; FilterFunc filter_func; - friend class FilterFn; + friend FilterFn; // Value constructor for use only in the filter function Filtered(FilterFunc in_filter_func, Container&& in_container) From efe0c77b24988ad76eb1c359bb32ff478b731538 Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 7 Apr 2016 00:30:23 -0700 Subject: [PATCH 108/596] adds explicit "u" to enumerate start val --- test/test_enumerate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_enumerate.cpp b/test/test_enumerate.cpp index 38b3a90a..5d0e67e6 100644 --- a/test/test_enumerate.cpp +++ b/test/test_enumerate.cpp @@ -50,7 +50,7 @@ TEST_CASE("Postfix ++ enumerate", "[enumerate]") { TEST_CASE("enumerate: with starting value", "[enumerate]") { std::string str = "hey"; - auto e = enumerate(str, 5); + auto e = enumerate(str, 5u); Vec v(std::begin(e), std::end(e)); Vec vc{{5, 'h'}, {6, 'e'}, {7, 'y'}}; From 3a8f11d6f1103b4a2bf4dca6f650a18bc7124f6e Mon Sep 17 00:00:00 2001 From: Ryan Haining Date: Thu, 7 Apr 2016 00:34:35 -0700 Subject: [PATCH 109/596] Adds IterToolFn to generalize the callables --- internal/iterbase.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/iterbase.hpp b/internal/iterbase.hpp index 64eae3e4..7d8acb0d 100644 --- a/internal/iterbase.hpp +++ b/internal/iterbase.hpp @@ -357,6 +357,22 @@ namespace iter { return {static_cast(*this), std::move(func)}; } }; + + // Pipeable Callable generator, where ItImpl is templated on the first + // argument to the call. + template