diff --git a/README.md b/README.md index 6f47820..ce8ed24 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,17 @@ It is a general-purpose library. The usage of no-STL, resource-tight embedded ap ## Features ### Higher-Order Functions -EFP supports major higher-order functions including `for_each`, `map`, `filter`, `foldl`, `foldr`, `from_function`, `for_index`, `for_each_with_index`, `cartesian_for_each`, `map_with_index`, `cartesian_map` etc. +EFP supports major higher-order functions including `for_each`, `map`, `filter`, `foldl`, `foldr`, `from_function`, `for_index`, `for_each_with_index`, `cartesian_for_each`, `map_with_index`, `cartesian_map` and many more. ### Zero-Copy Sequence Types Copying sequence is often an expensive operation yet does not necessary. Move semantic, introduced in C++ 11 somewhat eases the problem. However, the move helps little about stack sequence types like `std::array`, since moving such types is essentially a series of element-wise moves which is often no better than an element-wise copy. There is a better option, copy-elision (Return Value Optimization and Named Return Value Optimization). It makes returning heavy data free. Unfortunately, copy-elision is not guaranteed but at the compiler's discretion. (Since, C++ 17 some of them are guaranteed.) -EFP offers zero-copy, guaranteed copy-elision (RVO, NRVO) sequence types as solutions to the issue; `efp::Array`, `efp::Vector`, `efp::Vector`. Copy-elision of these types is guaranteed regardless of compiler and C++ standards. To be exact, these types could be copy-assigned but not copy-constructed. These types are also used as the default output types of mixed-type, n-ary operations. +EFP offers zero-copy, guaranteed copy-elision (RVO, NRVO) sequence type as solutions to the issue; `efp::Sequence`, or `efp::Array`, `efp::ArrVec`, `efp::Vector` as aliased name. Copy-elision of these types is guaranteed regardless of compiler and C++ standards. To be exact, these types could be copy-assigned but not copy-constructed. These types are also used as the default output types of mixed-type, n-ary operations. -### Type Agnostic APIs -EFP accepts C-style array, `std::array`, `std::vector`, `efp::Array`, `efp::ArrVec`, and `efp::Vector` as sequence arguments. APIs are generic on these types, which means there is (almost)no need to care about sequence container type. +### Compile-Time Polymorphism +HOFs of EFP accept `efp::Sequence` as sequence arguments. APIs are generic on these types, which means there is (almost)no need to care about sequence container type. Sequence-returning functions will return zero-copy sequences of EFP, which are either `efp::Array`, `efp::ArrVec`, or `efp::Vector` based on the types of argument sequences. The adequate type will be selected at compile time, based on if capacity and length are known in compile time, in a manner minimizing memory usage and avoiding allocation; - Static capacity && static length @@ -96,7 +96,7 @@ WIP EFP is tested with Catch2 with g++ and clang. ``` =============================================================================== -All tests passed (249 assertions in 54 test cases) +All tests passed (344 assertions in 70 test cases) ``` ## Requirements diff --git a/include/prelude_.hpp b/include/prelude_.hpp deleted file mode 100644 index 1e09418..0000000 --- a/include/prelude_.hpp +++ /dev/null @@ -1,969 +0,0 @@ -#ifndef PRELUDE_HPP_ -#define PRELUDE_HPP_ - -#include -#include -#include -#include - -#include "sfinae.hpp" -#include "enum_type.hpp" -#include "sequence.hpp" -#include "maybe.hpp" - -namespace efp -{ - // struct Unit - // { - // }; - - template - A id(const A &a) - { - return a; - } - - // ! WIP - // Composed - - // template - // struct Composed; - - // Composed - - template - struct Composed - { - const F &f; - const G &g; - - Composed(const F &f, const G &g) : f(f), g(g) {} - - template - - auto operator()(Arg &&arg) const -> decltype(f(g(std::forward(arg)))) - { - return f(g(std::forward(arg))); - } - }; - - // template - // struct Composed - // { - // const F &f; - // const Composed fs; - - // Composed(const F &f, const Fs &...fs) : f(f), fs(compose(fs...)) {} - - // template - - // inline auto operator()(Arg &&arg) -> decltype(f(fs(std::forward(arg)))) - // { - // return f(fs(std::forward(arg))); - // } - // }; - - // template - // inline auto operator*(F f, G g) -> Composed - // { - // return compose(f, g); - // } - - // compose - - template - auto compose(const F &f, const G &g) -> Composed - { - return Composed(f, g); - } - - // template - // auto compose(const F &f, const Fs &...fs) -> Composed - // { - // return Composed(f, fs...); - // } - - // execute_pack - - template - void execute_pack(Args... args) - { - } - - // AppendSequence_t - - template - using AppendSequence_t = - Conditional< - all_v(IsStaticCapacity::value...), - Conditional< - all_v(IsStaticLength::value...), - Array::value...)>, - ArrVec::value...)>>, - Vector>; - - // AppendReturn_t - template - using AppendReturn_t = AppendSequence_t, Head, Tail...>; - - // append - - template - Unit append_(A &result, int &idx, const B &seq) - { - for (auto elem : seq) - { - result[idx] = elem; - idx++; - } - return Unit{}; - } - - template - auto append(const Head &head, const Tail &...tail) - -> EnableIf< - all_v(IsStaticCapacity::value, IsStaticCapacity::value...) && all_v(IsStaticLength::value, IsStaticLength::value...), - AppendReturn_t> - { - AppendReturn_t result; - int idx{0}; - - execute_pack(append_(result, idx, head), append_(result, idx, tail)...); - - return result; - } - - template - auto append(const Head &head, const Tail &...tail) - -> EnableIf< - !all_v(IsStaticLength::value, IsStaticLength::value...), - AppendReturn_t> - { - // ! Error on int - const size_t result_length = sum_v((int)length(head), (int)length(tail)...); - - AppendReturn_t result(result_length); - int idx{0}; - - execute_pack(append_(result, idx, head), append_(result, idx, tail)...); - - return result; - } - - // min_length - - template - constexpr auto min_length(const SeqA &as) - -> Conditional< - IsStaticLength::value, - decltype(length(as)), - size_t> - { - return length(as); - } - - template - constexpr auto min_length(const Head &head, const Tail &...tail) - -> Conditional< - all_v(IsIntegralConst::value, IsIntegralConst::value...), - decltype(length(head)), - size_t> - { - return length(head) < min_length(tail...) ? length(head) : min_length(tail...); - } - - // for_each - - template &...)> - void for_each(const F &f, const Seqs &...seqs) - { - const int seq_length = min_length(seqs...); - - for (int i = 0; i < seq_length; ++i) - { - f(seqs[i]...); - } - } - - // for_eachi - - template &...)> - void for_eachi(const F &f, Seqs &...seqs) - { - const int seq_length = min_length(seqs...); - - for (int i = 0; i < seq_length; ++i) - { - f(seqs[i]...); - } - } - - // MapSequence_t - - template - using MapSequence_t = - Conditional< - all_v(IsStaticCapacity::value...), - Conditional< - all_v(IsStaticLength::value...), - Array::value>, - ArrVec::value>>, - Vector>; - - // MapReturn_t - - template - using MapReturn_t = MapSequence_t...>, Seqs...>; - - // map - - template - auto map(const F &f, const Seqs &...seqs) - -> EnableIf< - all_v(IsStaticCapacity::value...) && all_v(IsStaticLength::value...), - MapReturn_t> - { - // using R = CallReturn...>; - - MapReturn_t result; - - for (int i = 0; i < MinStaticCapacity::value; ++i) - { - result[i] = f(seqs[i]...); - } - - return result; - } - - template - auto map(const F &f, const Seqs &...seqs) - -> EnableIf< - !all_v(IsStaticLength::value...), - MapReturn_t> - { - const int result_length = min_length(seqs...); - - MapReturn_t result(result_length); - - for (int i = 0; i < result_length; ++i) - { - result[i] = f(seqs[i]...); - } - - return result; - } - - // MapWithIndexReturn_t - - template - using MapWithIndexReturn_t = - MapSequence_t...>, Seqs...>; - - // FilterReturn_t - - template - using FilterReturn_t = - Conditional< - IsStaticCapacity::value, - ArrVec, StaticCapacity::value>, - Vector>>; - - // filter - - template &...)> - auto filter(const F &f, const SeqA &as) - -> EnableIf< - IsStaticCapacity::value, - ArrVec, StaticCapacity::value>> - { - ArrVec, StaticCapacity::value> result; - - for (int i = 0; i < length(as); ++i) - { - const auto a = as[i]; - if (f(a)) - { - result.push_back(a); - } - } - - return result; - } - - template &...)> - auto filter(const F &f, const SeqA &as) - -> EnableIf< - !IsStaticCapacity::value, - Vector>> - { - const int sequance_length = length(as); - - Vector> result; - result.reserve(sequance_length * 2); - - for (int i = 0; i < sequance_length; ++i) - { - const auto a = as[i]; - if (f(a)) - { - result.push_back(a); - } - } - - return result; - } - - // foldl - - template &)> - R foldl(const F &f, const R &initial_value, const SeqA &as) - { - R result = initial_value; - - for (int i = 0; i < length(as); ++i) - { - result = f(result, as[i]); - } - - return result; - } - - // foldr - - template &, const R &)> - R foldr(const F &f, const R &initial_value, const SeqA &as) - { - R result = initial_value; - - for (int i = length(as) - 1; i > -1; --i) - { - result = f(as[i], result); - } - - return result; - } - - // FromFunctionReturn_t - - template - using FromFunctionReturn_t = Conditional< - IsIntegralConst::value, - Array, N::value>, - Vector>>; - - // from_function - - template - auto from_function(const N &length, const F &f) - -> EnableIf< - IsIntegralConst::value, - Array, N::value>> - { - Array, N::value> result; - - for (int i = 0; i < N::value; ++i) - { - result[i] = f(i); - } - - return result; - } - - template - auto from_function(const N &length, const F &f) - -> EnableIf< - !IsIntegralConst::value, - Vector>> - { - Vector> result(length); - - for (int i = 0; i < length; ++i) - { - result[i] = f(i); - } - - return result; - } - - // for_index - - template - void for_index(const F &f, const int i) - { - for (int i_ = 0; i_ < i; ++i_) - { - f(i_); - } - } - - // for_each_with_index - - template &...)> - void for_each_with_index(const F &f, const Seqs &...seqs) - { - const int seq_length = min_length(seqs...); - - for (int i = 0; i < seq_length; ++i) - { - f(i, seqs[i]...); - } - } - - // for_each_with_indexi - - template &...)> - void for_each_with_indexi(const F &f, Seqs &...seqs) - { - const int seq_length = min_length(seqs...); - - for (int i = 0; i < seq_length; ++i) - { - f(i, seqs[i]...); - } - } - - // cartesian_for_each - - template &)> - void cartesian_for_each(const F &f, const SeqA &as) - { - for_each(f, as); - } - - template &, const Element_t &...)> - void cartesian_for_each(const F &f, const SeqA &as, const Seqs &...seqs) - { - // ? Will it be optimized out to a compile time constatnt? - const int as_length = length(as); - Element_t a; - - for (int i = 0; i < as_length; ++i) - { - a = as[i]; - const auto inner = [=](Element_t... xs) - { - f(a, xs...); - }; - - cartesian_for_each(inner, seqs...); - } - } - - // cartesian_for_eachi - - template &)> - void cartesian_for_eachi(const F &f, SeqA &as) - { - for_eachi(f, as); - } - - template &, Element_t &...)> - void cartesian_for_eachi(const F &f, SeqA &as, Seqs &...seqs) - { - // ? Will it be optimized out to a compile time constatnt? - const int as_length = length(as); - Element_t a; - - for (int i = 0; i < as_length; ++i) - { - a = as[i]; - const auto inner = [=](Element_t... xs) - { - f(a, xs...); - }; - - cartesian_for_eachi(inner, seqs...); - } - } - - // map_with_index - - template &...)> - auto map_with_index(const F &f, const Seqs &...seqs) - -> EnableIf< - all_v(IsStaticCapacity::value...) && all_v(IsStaticLength::value...), - Array...>, MinStaticCapacity::value>> - { - using R = CallReturn...>; - - Array::value> result; - - for (int i = 0; i < MinStaticCapacity::value; ++i) - { - result[i] = f(i, seqs[i]...); - } - - return result; - } - - template &...)> - auto map_with_index(const F &f, const Seqs &...seqs) - -> EnableIf< - all_v(IsStaticCapacity::value...) && !all_v(IsStaticLength::value...), - ArrVec...>, MinStaticCapacity::value>> - { - using R = CallReturn...>; - - const int result_length = min_length(seqs...); - - ArrVec::value> result(result_length); - - for (int i = 0; i < result_length; ++i) - { - result[i] = f(i, seqs[i]...); - } - - return result; - } - - template &...)> - auto map_with_index(const F &f, const Seqs &...seqs) - -> EnableIf< - !all_v(IsStaticCapacity::value...), - Vector...>>> - { - using R = CallReturn...>; - - const int result_length = min_length(seqs...); - - Vector result(result_length); - - for (int i = 0; i < result_length; ++i) - { - result[i] = f(i, seqs[i]...); - } - - return result; - } - - // cartesian_map - // ! Maybe need to bechmark and optimize - template &...)> - auto cartesian_map(const F &f, const Seqs &...seqs) - -> EnableIf< - all_v(IsStaticCapacity::value...) && all_v(IsStaticLength::value...), - Array...>, StaticCapacityProduct::value>> - { - using R = CallReturn...>; - - Array::value> result; - int i = 0; - - const auto inner = [&](Element_t... xs) - { - result[i++] = f(xs...); - }; - - cartesian_for_each(inner, seqs...); - - return result; - } - - // todo Make both case as one. - template &...)> - auto cartesian_map(const F &f, const Seqs &...seqs) - -> EnableIf< - all_v(IsStaticCapacity::value...) && !all_v(IsStaticLength::value...), - ArrVec...>, StaticCapacityProduct::value>> - { - using R = CallReturn...>; - - const int result_length = size_v_product(length(seqs)...); - - ArrVec::value> result(result_length); - int i = 0; - - const auto inner = [&](Element_t... xs) - { - result[i++] = f(xs...); - }; - - cartesian_for_each(inner, seqs...); - - return result; - } - - template &...)> - auto cartesian_map(const F &f, const Seqs &...seqs) - -> EnableIf< - !all_v(IsStaticCapacity::value...), - Vector...>>> - { - using R = CallReturn...>; - - const int result_length = size_v_product(length(seqs)...); - - Vector result(result_length); - int i = 0; - - const auto inner = [&](Element_t... xs) - { - result[i++] = f(xs...); - }; - - cartesian_for_each(inner, seqs...); - - return result; - } - - // cartesian_for_index - - template - void cartesian_for_index(const F &f, const int &i) - { - for_index(f, i); - } - - template - void cartesian_for_index(const F &f, const int &i, const Ints &...is) - { - for (int i_ = 0; i_ < i; ++i_) - { - const auto inner = [=](const Ints &...is) - { f(i_, is...); }; - - cartesian_for_index(inner, is...); - } - } - - // // todo begin - - // // todo end - - // todo head - // ! Partial function. Make sure non empty - template - Element_t head(const SeqA &as) - { - return as[0]; - } - - // todo tail - // ! Partial function. Make sure non empty - template - auto tail(const SeqA &as) - -> VectorView> - { - return VectorView>{data(as) + 1, length(as) - 1}; - } - - // ! Partial function. Make sure non empty - template - auto tail(SeqA &as) - -> VectorView> - { - return VectorView>{data(as) + 1, length(as) - 1}; - } - - // todo init - // ! Partial function. Make sure non empty - template - auto init(const SeqA &as) - -> VectorView> - { - return VectorView>{data(as), length(as) - 1}; - } - - // ! Partial function. Make sure non empty - template - auto init(SeqA &as) - -> VectorView> - { - return VectorView>{data(as), length(as) - 1}; - } - - // todo last - // ! Partial function. Make sure non empty - template - Element_t last(const SeqA &as) - { - return as[length(as) - 1]; - } - - // todo is_null - - // using View_t = Conditional< - // template - // IsStaticLength::value, - // ArrayView>, - // VectorView>>; - - // todo take - - // template - // auto take(const N &n, SeqA &as) - // -> EnableIf< - // IsIntegralConst::value && IsStaticLength::value, - // ArrayView, bound_v(0, StaticLength::value, N::value)>> - // { - // return ArrayView, bound_v(0, StaticLength::value, N::value)>{data(as)}; - // } - - // template - // auto take(const N &n, SeqA &as) - // -> EnableIf< - // !IsIntegralConst::value && IsStaticLength::value, - // VectorView>> - // { - // return VectorView>{data(as), (size_t)bound_v(0, length(as), n)}; - // } - - template - auto take(int n, const SeqA &as) - -> VectorView> - { - return VectorView>{data(as), (size_t)bound_v(0, (int)length(as), n)}; - } - - template - auto take(int n, SeqA &as) - -> VectorView> - { - return VectorView>{data(as), (size_t)bound_v(0, (int)length(as), n)}; - } - - // drop - - // template - // auto drop(const N &n, SeqA &as) - // -> EnableIf< - // IsIntegralConst::value && IsStaticLength::value, - // ArrayView, bound_v(0, StaticLength::value, StaticLength::value - N::value)>> - // { - // // ! What if larger than n? maybe last with 0? - // return ArrayView, bound_v(0, StaticLength::value, StaticLength::value - N::value)>{data(as) + n}; - // } - - // template - // auto drop(const N &n, SeqA &as) - // -> EnableIf< - // IsIntegralConst::value && IsStaticLength::value, - // ArrayView, StaticLength::value - N::value>> - // { - // // ! What if larger than n? maybe last with 0? - // return ArrayView, StaticLength::value - N::value>{data(as) + n}; - // } - - // template - // auto drop(const N &n, const SeqA &as) - // -> EnableIf< - // IsIntegralConst::value && IsStaticLength::value, - // ArrayView, StaticLength::value - N::value>> - // { - // return ArrayView, StaticLength::value - N::value>{data(as) + n}; - // } - - // template - // auto drop(const N &n, SeqA &as) - // -> EnableIf< - // !IsIntegralConst::value && IsStaticLength::value, - // VectorView>> - // { - // // ! What if larger than n? maybe last with 0? - // return VectorView>{data(as) + n, (size_t)bound_v(0, length(as), length(as) - n)}; - // } - - // template - // auto drop(const N &n, SeqA &as) - // -> EnableIf< - // !IsIntegralConst::value && IsStaticLength::value, - // VectorView>> - // { - // // ! What if larger than n? maybe last with 0? - // return VectorView>{data(as) + n, length(as) - n}; - // } - - // template - // auto drop(const N &n, const SeqA &as) - // -> EnableIf< - // !IsIntegralConst::value && IsStaticLength::value, - // VectorView>> - // { - // return VectorView>{data(as) + n, length(as) - n}; - // } - - template - auto drop(int n, const SeqA &as) - -> VectorView> - { - auto as_length = length(as); - auto bound_n = (size_t)bound_v(0, (int)as_length, n); - return VectorView>{data(as) + bound_n, as_length - bound_n}; - } - - template - auto drop(int n, SeqA &as) - -> VectorView> - { - auto as_length = length(as); - auto bound_n = (size_t)bound_v(0, (int)as_length, n); - return VectorView>{data(as) + bound_n, as_length - bound_n}; - } - - // elem - - template - bool elem(const Element_t &a, const SeqA &as) - { - const int length_as = length(as); - - for (int i = 0; i < length_as; ++i) - { - if (as[i] == a) - { - return true; - } - } - - return false; - } - - // elem_index - - template - Maybe elem_index(const Element_t &a, const SeqA &as) - { - const int length_as = length(as); - - for (int i = 0; i < length_as; ++i) - { - if (as[i] == a) - { - return i; - } - } - - return Nothing{}; - } - - // IndicesReturn_t - - template - using IndicesReturn_t = - Conditional< - IsStaticCapacity::value, - ArrVec::value>, - Vector>; - - // elem_indices - - template - auto elem_indices(const Element_t &a, const SeqA &as) - -> EnableIf< - IsStaticCapacity::value, - IndicesReturn_t> - { - IndicesReturn_t result; - - for (int i = 0; i < length(as); ++i) - { - if (a == as[i]) - { - result.push_back(i); - } - } - - return result; - } - - template - auto elem_indices(const Element_t &a, const SeqA &as) - -> EnableIf< - !IsStaticCapacity::value, - IndicesReturn_t> - { - const int length_as = length(as); - - IndicesReturn_t result; - result.reserve(length_as); - - for (int i = 0; i < length_as; ++i) - { - if (a == as[i]) - { - result.push_back(i); - } - } - - return result; - } - - // find - - template &)> - bool find(const F &f, const SeqA &as) - { - for (int i = 0; i < length(as); ++i) - { - const Element_t a = as[i]; - if (f(a)) - { - return true; - } - } - - return false; - } - - // find_index - - template &)> - auto find_index(const F &f, const SeqA &as) - -> Maybe - { - for (int i = 0; i < length(as); ++i) - { - if (f(as[i]) == true) - { - return i; - } - } - - return Nothing{}; - } - - // find_indices - - template &)> - auto find_indices(const F &f, const SeqA &as) - -> EnableIf< - IsStaticCapacity::value, - IndicesReturn_t> - { - const int length_as = length(as); - IndicesReturn_t result; - - for (int i = 0; i < length_as; ++i) - { - if (f(as[i])) - { - result.push_back(i); - } - } - - return result; - } - - template &)> - auto find_indices(const F &f, const SeqA &as) - -> EnableIf< - !IsStaticCapacity::value, - IndicesReturn_t> - { - const int as_length = length(as); - - IndicesReturn_t result; - result.reserve(as_length); - - for (int i = 0; i < as_length; ++i) - { - if (f(as[i])) - { - result.push_back(i); - } - } - - return result; - } -} -#endif \ No newline at end of file diff --git a/include/sequence.hpp b/include/sequence.hpp index 8f104bf..da10d63 100644 --- a/include/sequence.hpp +++ b/include/sequence.hpp @@ -29,9 +29,6 @@ namespace efp static constexpr int ct_len = Trait::ct_len; static constexpr int ct_cap = Trait::ct_cap; - // static_assert(ct_len >= -1, "ct_length must greater or equal than -1."); - // static_assert(ct_cap >= -1, "ct_capacity must greater or equal than -1."); - const Element &operator[](int index) const { return derived()[index]; @@ -570,9 +567,6 @@ namespace efp using Element = A; static constexpr int ct_len = ct_length; static constexpr int ct_cap = ct_capacity; - - // static_assert(ct_len >= -1, "ct_length must greater or equal than -1."); - // static_assert(ct_cap >= -1, "ct_capacity must greater or equal than -1."); }; // Should have all these three template parameter not to break static link @@ -978,9 +972,6 @@ namespace efp using Element = A; static constexpr int ct_len = ct_length; static constexpr int ct_cap = ct_capacity; - - // static_assert(ct_len >= -1, "ct_length must greater or equal than -1."); - // static_assert(ct_cap >= -1, "ct_capacity must greater or equal than -1."); }; // todo STL only diff --git a/include/sequence_.hpp b/include/sequence_.hpp deleted file mode 100644 index a65913e..0000000 --- a/include/sequence_.hpp +++ /dev/null @@ -1,1017 +0,0 @@ -#ifndef SEQUENCE_HPP_ -#define SEQUENCE_HPP_ - -#include - -#include "sfinae.hpp" - -namespace efp -{ - template - class ArrayProxy_ : public std::array - { - public: - using std::array::array; - ArrayProxy_(const ArrayProxy_ &) = delete; - ArrayProxy_(ArrayProxy_ &&) = delete; - - // Assignment operators - ArrayProxy_ &operator=(const ArrayProxy_ &) = default; - ArrayProxy_ &operator=(ArrayProxy_ &&) = default; - - // Variadic constructor for the derived class - template - ArrayProxy_(Args &&...args) : std::array{{std::forward(args)...}} {} - }; - - template - class Array : public ArrayProxy_ - { - public: - using ArrayProxy_::ArrayProxy_; - Array(const Array &); // Not emplemented by design for RVO, NRVO enforcement - Array(Array &&); // Not emplemented by design for RVO, NRVO enforcement - - // Assignment operator - Array &operator=(const Array &) = default; - Array &operator=(Array &&) = default; - - // Variadic constructor for the derived class - template - Array(Args &&...args) : ArrayProxy_{std::forward(args)...} {} - }; - - // template - // class Array : std::array - // { - // public: - // // Type aliases to match std::array - // using value_type = A; - // using size_type = size_t; - - // // Default constructor - // Array() = default; // Unpredicatable data_ - // Array(const Array &); // Not emplemented by design for RVO, NRVO enforcement - // Array(Array &&); // Not emplemented by design for RVO, NRVO enforcement - - // template - // Array(Args &&...args) - // : data_{std::forward(args)...} {} - - // // Assignment - - // Array &operator=(const Array &other) - // { - // if (this != &other) - // { - // for (size_t i = 0; i < N; ++i) - // { - // data_[i] = other.data_[i]; - // } - // } - // return *this; - // } - - // // Accessors - // // ! Temp no constexpr - // A &operator[](size_type index) - // { - // return data_[index]; - // } - - // constexpr const A &operator[](size_type index) const - // { - // return data_[index]; - // } - - // inline constexpr size_type size() const noexcept - // { - // return N; - // } - - // // Iterators - // A *begin() noexcept - // { - // return data_; - // } - - // const A *begin() const noexcept - // { - // return data_; - // } - - // A *end() noexcept - // { - // return data_ + N; - // } - - // const A *end() const noexcept - // { - // return data_ + N; - // } - - // bool empty() const noexcept - // { - // return N == 0; - // } - - // private: - // A data_[N]; - // }; - - // template - // bool operator==(const Array &lhs, const Array &rhs) - // { - // return std::equal(lhs.begin(), lhs.end(), rhs.begin()); - // } - - template - class ArrVec - { - public: - using value_type = A; - using size_type = size_t; - - // Constructors - ArrVec() : size_(0) {} - ArrVec(const size_t s) : size_(0) {} // Unpredicatable data_ - ArrVec(const ArrVec &); // Not emplemented by design for RVO, NRVO enforcement - ArrVec(ArrVec &&); // Not emplemented by design for RVO, NRVO enforcement - template - ArrVec(const Args &...args) - : data_{args...}, - size_(sizeof...(args)) {} - - // Assignment - - ArrVec &operator=(const ArrVec &other) - { - if (this != &other) - { - size_ = other.size_; - for (size_t i = 0; i < size_; ++i) - { - data_[i] = other.data_[i]; - } - } - return *this; - } - - // Accessors - A &operator[](const size_type index) - { - return data_[index]; - } - - const A &operator[](const size_type index) const - { - return data_[index]; - } - - // Modifiers - void push_back(const value_type &value) - { - if (size_ < Capacity) - { - data_[size_] = value; - ++size_; - } - } - - void pop_back() - { - if (size_ > 0) - { - --size_; - } - } - - // Capacity - constexpr size_type capacity() const noexcept - { - return Capacity; - } - - // size - size_type size() const noexcept - { - return size_; - } - - A *data() - { - return data_; - } - - const A *data() const - { - return data_; - } - - // Iterators - A *begin() noexcept - { - return data_; - } - - const A *begin() const noexcept - { - return data_; - } - - A *end() noexcept - { - return data_ + size_; - } - - const A *end() const noexcept - { - return data_ + size_; - } - - bool empty() const noexcept - { - return size_ == 0; - } - - private: - A data_[Capacity]; - size_type size_; - }; - - template - bool operator==(const ArrVec &lhs, const ArrVec &rhs) - { - return std::equal(lhs.begin(), lhs.end(), rhs.begin()); - } - - // Vector - - template - class VectorProxy_ : public std::vector - { - public: - using std::vector::vector; - VectorProxy_(const VectorProxy_ &) = delete; - VectorProxy_(VectorProxy_ &&) = delete; - - // Assignment operators - VectorProxy_ &operator=(const VectorProxy_ &) = default; - VectorProxy_ &operator=(VectorProxy_ &&) = default; - }; - - template - class Vector : public VectorProxy_ - { - public: - using VectorProxy_::VectorProxy_; - Vector(const Vector &); // Not emplemented by design for RVO, NRVO enforcement - Vector(Vector &&); // Not emplemented by design for RVO, NRVO enforcement - - // Assignment operators - Vector &operator=(const Vector &) = default; - Vector &operator=(Vector &&) = default; - }; - - // template - // class Vector - // { - // public: - // // Type aliases - // using value_type = A; - // using size_type = size_t; - - // // Default constructor - // Vector() : data_(nullptr), size_(0), capacity_(0) {} - // Vector(const size_t size) : data_(new A[size * 2]), size_(size), capacity_(size * 2) {} // Unpredicatable data_ - // Vector(const Vector &); // Not emplemented by design for RVO, NRVO enforcement - // Vector(Vector &&); // Not emplemented by design for RVO, NRVO enforcement - // template - // Vector(const Args &...args) - // : data_(new A[sizeof...(args) * 2]), - // size_(sizeof...(args)), - // capacity_(sizeof...(args) * 2) - // { - // int i = 0; - // for (auto arg : std::initializer_list::type>{args...}) - // data_[i++] = arg; - // } - - // // Destructor - // ~Vector() - // { - // delete[] data_; - // } - - // // Assignment - - // Vector &operator=(const Vector &other) - // { - // if (this != &other) - // { - // const size_t other_size = other.size(); - // if (capacity_ < other_size) - // { - // reserve(other.capacity()); - // } - - // for (size_t i = 0; i < other_size; ++i) - // { - // data_[i] = other.data_[i]; - // } - // size_ = other_size; - // } - // return *this; - // } - - // // Element access - // A &operator[](const size_type index) - // { - // return data_[index]; - // } - - // const A &operator[](const size_type index) const - // { - // return data_[index]; - // } - - // // Modifiers - // void push_back(const A &value) - // { - // if (size_ == capacity_) - // { - // reserve(capacity_ == 0 ? 1 : capacity_ * 2); - // } - // data_[size_++] = value; - // } - - // void pop_back() - // { - // if (size_ > 0) - // { - // --size_; - // } - // } - - // // Capacity - // size_type capacity() const noexcept - // { - // return capacity_; - // } - - // // size - // size_type size() const noexcept - // { - // return size_; - // } - - // // Reserve capacity - // void reserve(const size_type new_capacity) - // { - // if (new_capacity > capacity_) - // { - // A *new_data = new A[new_capacity]; - // for (size_type i = 0; i < size_; ++i) - // { - // new_data[i] = data_[i]; - // } - // delete[] data_; - // data_ = new_data; - // capacity_ = new_capacity; - // } - // } - - // // Resizing the vector - // void resize(const size_type new_size) - // { - // if (new_size > capacity_) - // { - // reserve(new_size); - // } - // size_ = new_size; - // } - - // // Iterators - // A *begin() noexcept - // { - // return data_; - // } - - // const A *begin() const noexcept - // { - // return data_; - // } - - // A *end() noexcept - // { - // return data_ + size_; - // } - - // const A *end() const noexcept - // { - // return data_ + size_; - // } - - // bool empty() const noexcept - // { - // return size_ == 0; - // } - - // private: - // A *data_; - // size_type size_; - // size_type capacity_; - // }; - - // template - // bool operator==(const Vector &lhs, const Vector &rhs) - // { - // return std::equal(lhs.begin(), lhs.end(), rhs.begin()); - // } - - // ArrayView - - template - class ArrayView - { - public: - using value_type = A; - using size_type = size_t; - using pointer_type = A *; - - ArrayView(pointer_type data) - : data_(data) - { - } - - ArrayView(const ArrayView &other) - : data_(other.data_) - { - } - - ArrayView(ArrayView &&other) noexcept - : data_(other.data_) - { - other.data_ = nullptr; - } - - ~ArrayView() - { - } - - friend bool operator==(const ArrayView &lhs, const ArrayView &rhs) - { - return lhs.data_ == rhs.data_; - } - - A &operator[](size_type index) - { - return data_[index]; - } - - constexpr const A &operator[](size_type index) const - { - return data_[index]; - } - - constexpr size_type size() const noexcept - { - return N; - } - - A *data() - { - return data_; - } - - const A *data() const - { - return data_; - } - - // Iterators - A *begin() noexcept - { - return data_; - } - - const A *begin() const noexcept - { - return data_; - } - - A *end() noexcept - { - return data_ + N; - } - - const A *end() const noexcept - { - return data_ + N; - } - - bool empty() const noexcept - { - return N == 0; - } - - private: - pointer_type data_; - }; - - // VectorView - - template - class VectorView - { - public: - using value_type = A; - using size_type = size_t; - using pointer_type = Conditional< - IsConst::value, - const A *, - A *>; - - VectorView(pointer_type data, const size_t size) - : data_(data), size_(size) - { - } - VectorView(const VectorView &other) - : data_(other.data_), size_(other.size_) - { - } - - VectorView(VectorView &&other) noexcept - : data_(other.data_), size_(other.size_) - { - other.data_ = nullptr; - other.size_ = 0; - } - ~VectorView() - { - } - - friend bool operator==(const VectorView &lhs, const VectorView &rhs) - { - return (lhs.data_ == rhs.data_) && (lhs.size_ == rhs.size_); - } - - A &operator[](const size_type index) - { - return data_[index]; - } - - const A &operator[](const size_type index) const - { - return data_[index]; - } - - // Capacity - // ? Do I need this? - size_type - capacity() const noexcept - { - return size_; - } - - // size - size_type size() const noexcept - { - return size_; - } - - A *data() - { - return data_; - } - - const A *data() const - { - return data_; - } - - // Iterators - A *begin() noexcept - { - return data_; - } - - const A *begin() const noexcept - { - return data_; - } - - A *end() noexcept - { - return data_ + size_; - } - - const A *end() const noexcept - { - return data_ + size_; - } - - bool empty() const noexcept - { - return size_ == 0; - } - - private: - pointer_type data_; - size_type size_; - }; - - // template - // bool operator==(const VectorView &lhs, const VectorView &rhs) - // { - // return (lhs.data_ == rhs.data_) && (lhs.size_ == rhs.size_); - // } - - // IsStaticCapacity - - template - struct IsStaticCapacity : std::false_type - { - }; - - template - struct IsStaticCapacity> : std::true_type - { - }; - - template - struct IsStaticCapacity> : std::true_type - { - }; - - template - struct IsStaticCapacity> : std::true_type - { - }; - - template - struct IsStaticCapacity : std::true_type - { - }; - - template - struct IsStaticCapacity : IsStaticCapacity - { - }; - - template - struct IsStaticCapacity : IsStaticCapacity - { - }; - - // AreAllStaticCapacity - - template - struct AreAllStaticCapacity - { - static constexpr bool value = all_v(IsStaticCapacity::value...); - }; - - // StaticCapacity - - template - struct StaticCapacity - { - static constexpr size_t value = 0; - }; - - template - struct StaticCapacity - { - static constexpr size_t value = N; - }; - - template - struct StaticCapacity> - { - static constexpr size_t value = N; - }; - - template - struct StaticCapacity> - { - static constexpr size_t value = N; - }; - - template - struct StaticCapacity> - { - static constexpr size_t value = N; - }; - - template - struct StaticCapacity : StaticCapacity - { - }; - - template - struct StaticCapacity : StaticCapacity - { - }; - - // IsStaticLength - - template - struct IsStaticLength : std::false_type - { - }; - - template - struct IsStaticLength> : std::true_type - { - }; - - template - struct IsStaticLength> : std::true_type - { - }; - - template - struct IsStaticLength : std::true_type - { - }; - - template - struct IsStaticLength : IsStaticLength - { - }; - - template - struct IsStaticLength : IsStaticLength - { - }; - - // StaticLength - - template - struct StaticLength; - - template - struct StaticLength> - { - static constexpr size_t value = N; - }; - - template - struct StaticLength> - { - static constexpr size_t value = N; - }; - - template - struct StaticLength - { - static constexpr size_t value = N; - }; - - template - struct StaticLength : StaticLength - { - }; - - template - struct StaticLength : StaticLength - { - }; - - // length - - template - constexpr auto length(const SeqA &as) - -> EnableIf::value, - size_t> - { - return as.size(); - } - - template - constexpr auto length(const SeqA &as) - -> EnableIf::value, - IntegralConst::value>> - { - return IntegralConst::value>{}; - } - - template - constexpr auto length(const A (&)[N]) - -> IntegralConst - { - return IntegralConst{}; - } - - // StaticSizeT - - // template - // using StaticSizeT = IntegralConst; - - // min_size_v - - template - constexpr A min_size_v(const A &value) - { - return value; - } - - template - constexpr auto min_size_v(const Head &head, const Tail &...tail) - -> typename std::conditional< - all_v(IsIntegralConst::value, IsIntegralConst::value...), - Head, - size_t>::type - { - return head < min_size_v(tail...) ? head : min_size_v(tail...); - } - - // size_v_product - - template - constexpr A size_v_product(const A &value) - { - return value; - } - - template - constexpr auto size_v_product(const Head &head, const Tail &...tail) - -> typename std::conditional< - all_v(IsIntegralConst::value, IsIntegralConst::value...), - Head, - size_t>::type - { - return head * size_v_product(tail...); - } - - // MinStaticCapacity - - template - struct MinStaticCapacity; - - template - struct MinStaticCapacity - { - static constexpr size_t value = StaticCapacity::value; - }; - - template - struct MinStaticCapacity - { - static constexpr size_t head = StaticCapacity::value; - static constexpr size_t tail = min_size_v(StaticCapacity::value...); - static constexpr size_t value = head < tail ? head : tail; - }; - - // StaticCapacityProduct - - template - struct StaticCapacityProduct; - - template - struct StaticCapacityProduct - { - static constexpr size_t value = StaticCapacity::value; - }; - - template - struct StaticCapacityProduct - { - static constexpr size_t value = StaticCapacity::value * StaticCapacityProduct::value; - }; - - // ElementType - - template - struct ElementType - { - using type = typename A::value_type; - }; - - template - struct ElementType - { - using type = A; - }; - - template - struct ElementType : ElementType - { - }; - - template - struct ElementType : ElementType - { - }; - - // Element_t - - template - using Element_t = typename ElementType::type; - - // ViewElementType - - template - struct ViewElementType - { - using type = typename A::value_type; - }; - - template - struct ViewElementType - { - using type = const typename A::value_type; - }; - - template - struct ViewElementType - { - using type = A; - }; - - template - struct ViewElementType - { - using type = const A; - }; - - template - struct ViewElementType : ViewElementType - { - }; - - template - struct ViewElementType : ViewElementType - { - }; - - // ViewElement_t - - template - using ViewElement_t = typename ViewElementType::type; - - // data - - // template - // constexpr auto data(const SeqA &as) - // -> decltype(as.data()) - // { - // return as.data(); - // } - - // template - // constexpr A *data(A (&as)[N]) - // { - // return (A *)as; - // } - - // template - // constexpr const A *data(const A (&as)[N]) - // { - // return (const A *)as; - // } - - template - constexpr auto data(const SeqA &as) - -> const Element_t * - { - return as.data(); - } - - template - constexpr auto data(SeqA &as) - -> Element_t * - { - return as.data(); - } - - template - constexpr A *data(A (&as)[N]) - { - return (A *)as; - } - - template - constexpr const A *data(const A (&as)[N]) - { - return (const A *)as; - } - - // end - - template - constexpr const Element_t *end(const SeqA &as) - { - return data(as) + length(as); - } - - template - constexpr Element_t *end(SeqA &as) - { - return data(as) + length(as); - } - -}; - -#endif \ No newline at end of file diff --git a/test/prelude__test.hpp b/test/prelude__test.hpp deleted file mode 100644 index a446174..0000000 --- a/test/prelude__test.hpp +++ /dev/null @@ -1,723 +0,0 @@ -#ifndef PRELUDE_TEST_HPP_ -#define PRELUDE_TEST_HPP_ - -#include "catch2/catch_test_macros.hpp" - -#include "efp.hpp" -#include "test_common.hpp" - -using namespace efp; - -// ! WIP - -TEST_CASE("compose") -{ - SECTION("pure0") - { - auto add_1 = [](int x) - { - return x + 1; - }; - - auto times_2 = [](int x) - { - return x * 2; - }; - - auto composed = compose(add_1, times_2); - // auto composed_with_operator = add_1 * times_2; - - CHECK(composed(2) == 5); - // CHECK(composed_with_operator(2) == 5); - } - - SECTION("pure1") - { - auto add_1 = [](int x) - { - return x + 1; - }; - - auto devide_2 = [](int x) - { - return x / 2.; - }; - - auto composed = compose(devide_2, add_1); - CHECK(composed(2) == 1.5); - } - - SECTION("side-effect") - { - int i = 0; - - auto i_plusplus = [&](int x) - { - i += x; - return i; - }; - - auto times_2 = [](int x) - { - return x * 2; - }; - - auto composed = compose(times_2, i_plusplus); - CHECK(composed(2) == 4); - CHECK(i == 2); - } - - // SECTION("n-ary") - // { - // auto add_1 = [](int x) - // { - // return x + 1; - // }; - - // auto devide_2 = [](int x) - // { - // return x / 2.; - // }; - - // auto composed = compose(devide_2, add_1, square); - // CHECK(composed(2) == 2.5); - // } -} - -// TEST_CASE("IsStaticCapacity") -// { -// CHECK(IsStaticCapacity::value == true); -// CHECK(IsStaticCapacity>::value == true); -// CHECK(IsStaticCapacity>::value == false); -// } - -// TEST_CASE("AreAllStaticCapacity") -// { -// CHECK(AreAllStaticCapacity::value == true); -// CHECK(AreAllStaticCapacity>::value == true); -// CHECK(AreAllStaticCapacity>::value == true); -// CHECK(AreAllStaticCapacity>::value == false); -// CHECK(AreAllStaticCapacity, std::vector>::value == false); -// } - -TEST_CASE("append") -{ - SECTION("Array") - { - Array res{1., 2., 3., 1., 2., 3.}; - CHECK(append(std_array_3, array_3) == res); - } - - SECTION("ArrVec") - { - ArrVec res{1., 2., 3., 1., 2., 3.}; - CHECK(append(array_vector_3, array_3) == res); - } - - SECTION("Array") - { - Vector res{1., 2., 3., 1., 2., 3.}; - CHECK(append(std_array_3, vector_3) == res); - } -} - -TEST_CASE("for_each") -{ - int res_1 = 0; - auto add_1 = [&](int x) - { - res_1 += x; - }; - - for_each(add_1, c_array_3); - CHECK(res_1 == 6); - - double res_2 = 0.; - auto add_2 = [&](double x) - { - res_2 += x; - }; - - for_each(add_2, std_array_3); - CHECK(res_2 == 6.); - - double res_3 = 0.; - auto add_3 = [&](double x) - { - res_3 += x; - }; - - for_each(add_3, std_vector_3); - CHECK(res_3 == 6.); - - double res_4 = 0.; - auto add_product = [&](double x1, double x2) - { - res_4 += x1 * x2; - }; - - for_each(add_product, std_vector_3, c_array_3); - CHECK(res_4 == 14.); - - double res_5 = 0.; - - auto add_product_2 = [&](double x1, double x2) - { - res_5 += x1 * x2; - }; - - for_each(add_product_2, vector_view_3, vector_view_5); - CHECK(res_5 == 14.); -} - -TEST_CASE("for_eachi") -{ - int res_1[3]; - auto set_42 = [](int &x) - { - x = 42; - }; - - for_eachi(set_42, res_1); - - const auto is_42 = [](int x) - { return x == 42; }; - - CHECK(foldl(and_v, true, map(is_42, res_1)) == true); - - std::array res_2; - - for_eachi(set_42, res_2); - CHECK(res_2 == std::array{42, 42, 42}); - - Vector res_3{0, 0, 0}; - - for_eachi(set_42, res_3); - CHECK(res_3 == Vector{42, 42, 42}); - - SECTION("ArrayView") - { - int c_arr[3] = {0, 1, 2}; - ArrayView arr_view{&c_arr[0]}; - - for_eachi([](int &x) - { x = 2 * x; }, - arr_view); - - CHECK((c_arr[0] == 0 && c_arr[1] == 2 && c_arr[2] == 4)); - } -} - -TEST_CASE("map") -{ - SECTION("c style array") - { - auto square = [](int x) - { - return x * x; - }; - - CHECK(map(square, c_array_3) == Array{1, 4, 9}); - } - - SECTION("std::vector") - { - auto square = [](double x) - { - return x * x; - }; - - CHECK(map(square, std_vector_3) == Vector{1., 4., 9.}); - } - - SECTION("binary of std::array, std::vecor") - { - auto plus = [](double lhs, double rhs) - { - return lhs + rhs; - }; - - CHECK(map(plus, std_array_3, std_vector_3) == Vector{2., 4., 6.}); - } -} - -TEST_CASE("filter") -{ - SECTION("even c style array") - { - auto is_even = [](double x) - { - return (int)x % 2 == 0; - }; - - CHECK(filter(is_even, c_array_3) == ArrVec{2.}); - } - - SECTION("odd std::vector") - { - auto is_odd = [](double x) - { - return (int)x % 2 != 0; - }; - - CHECK(filter(is_odd, std_vector_3) == Vector{1., 3.}); - } -} - -TEST_CASE("foldl") -{ - SECTION("plus on c style arary") - { - CHECK(foldl(plus, 0, c_array_5) == 15); - } - - SECTION("times on std::vectors arary") - { - CHECK(foldl(times, 1., std_vector_3) == 6.); - } -} - -TEST_CASE("foldr") -{ - SECTION("plus on c style arary") - { - auto plus = [](int lhs, int rhs) - { - return lhs + rhs; - }; - CHECK(foldr(plus, 0, c_array_5) == 15); - } - - SECTION("times on std::vectors arary") - { - auto times = [](double lhs, double rhs) - { - return lhs * rhs; - }; - CHECK(foldr(times, 1., std_vector_3) == 6.); - } -} - -TEST_CASE("from_function") -{ - SECTION("Array") - { - auto plus_one = [](int i) - { - return i + 1; - }; - - CHECK(from_function(IntegralConst{}, plus_one) == Array{1, 2, 3}); - } - - SECTION("DynamicArray") - { - auto plus_one = [](int i) - { - return i + 1; - }; - - CHECK(from_function(3, plus_one) == Vector{1, 2, 3}); - } -} - -TEST_CASE("for_index") -{ - int res = 0; - - auto add_to_res = [&](int i) - { - res += i; - }; - - for_index(add_to_res, 0); - CHECK(res == 0); - for_index(add_to_res, 3); - CHECK(res == 3); - for_index(add_to_res, -1); - CHECK(res == 3); -} - -TEST_CASE("for_each_with_index") -{ - Array res; - - auto product = [&](int i, int x0, int x1) - { - res[i] = x0 * x1; - }; - - for_each_with_index(product, c_array_3, std_vector_5); - CHECK(res == Array{1, 4, 9}); -} - -TEST_CASE("cartesian_for_each") -{ - std::vector res; - auto as = std::array{1, 2}; - auto bs = std::array{1, 3}; - - auto push_res = [&](int x0, int x1) - { - res.push_back(x0 * x1); - }; - - cartesian_for_each(push_res, as, bs); - CHECK(res == std::vector{1, 3, 2, 6}); -} - -TEST_CASE("map_with_index") -{ - SECTION("c style array") - { - auto times = [](int lhs, int rhs) - { - return lhs * rhs; - }; - - CHECK(map_with_index(times, c_array_3) == Array{0, 2, 6}); - } - - SECTION("std::vector") - { - auto times = [](double lhs, double rhs) - { - return lhs * rhs; - }; - - CHECK(map_with_index(times, std_vector_3) == Vector{0., 2., 6.}); - } - - SECTION("binary of std::array, std::vecor") - { - auto product = [](int i, double a, double b) - { - return i * a * b; - }; - - CHECK(map_with_index(product, std_array_3, std_vector_3) == Vector{0., 4., 18.}); - } -} - -TEST_CASE("cartesian_map") -{ - auto as = std::array{1, 2}; - auto bs = std::array{1, 3}; - - auto res = cartesian_map(times, as, bs); - CHECK(res == Array{1, 3, 2, 6}); -} - -TEST_CASE("cartesian_for_index") -{ - Vector res; - const auto f = [&](int a, int b) - { return res.push_back(a * b); }; - - cartesian_for_index(f, 2, 3); - CHECK(res == Vector{0, 0, 0, 0, 1, 2}); -} - -// todo sequence view - -TEST_CASE("head") -{ - auto std_array = std::array{1, 2, 3}; - auto std_vector = std::vector{1, 2, 3}; - auto array = Array{1, 2, 3}; - auto arrvec = ArrVec{1, 2, 3}; - auto vector = Vector{1, 2, 3}; - - CHECK(head(std_array) == 1); - CHECK(head(std_vector) == 1); - CHECK(head(array) == 1); - CHECK(head(arrvec) == 1); - CHECK(head(vector) == 1); -} - -TEST_CASE("tail") -{ - SECTION("const") - { - const auto std_array = std::array{1, 2, 3}; - const auto std_vector = std::vector{1, 2, 3}; - const auto array = Array{1, 2, 3}; - const auto arrvec = ArrVec{1, 2, 3}; - const auto vector = Vector{1, 2, 3}; - - CHECK(tail(std_array) == VectorView{data(std_array) + 1, length(std_array) - 1}); - CHECK(tail(std_vector) == VectorView{data(std_vector) + 1, length(std_vector) - 1}); - CHECK(tail(array) == VectorView{data(array) + 1, length(array) - 1}); - CHECK(tail(arrvec) == VectorView{data(arrvec) + 1, length(arrvec) - 1}); - CHECK(tail(vector) == VectorView{data(vector) + 1, length(vector) - 1}); - } - - SECTION("non const") - { - std::array std_array{1, 2, 3}; - std::vector std_vector{1, 2, 3}; - Array array{1, 2, 3}; - ArrVec arrvec{1, 2, 3}; - Vector vector{1, 2, 3}; - - CHECK(tail(std_array) == VectorView{data(std_array) + 1, length(std_array) - 1}); - CHECK(tail(std_vector) == VectorView{data(std_vector) + 1, length(std_vector) - 1}); - CHECK(tail(array) == VectorView{data(array) + 1, length(array) - 1}); - CHECK(tail(arrvec) == VectorView{data(arrvec) + 1, length(arrvec) - 1}); - CHECK(tail(vector) == VectorView{data(vector) + 1, length(vector) - 1}); - } -} - -TEST_CASE("init") -{ - SECTION("const") - { - const auto std_array = std::array{1, 2, 3}; - const auto std_vector = std::vector{1, 2, 3}; - const auto array = Array{1, 2, 3}; - const auto arrvec = ArrVec{1, 2, 3}; - const auto vector = Vector{1, 2, 3}; - - CHECK(init(std_array) == VectorView{data(std_array), length(std_array) - 1}); - CHECK(init(std_vector) == VectorView{data(std_vector), length(std_vector) - 1}); - CHECK(init(array) == VectorView{data(array), length(array) - 1}); - CHECK(init(arrvec) == VectorView{data(arrvec), length(arrvec) - 1}); - CHECK(init(vector) == VectorView{data(vector), length(vector) - 1}); - } - - SECTION("non const") - { - std::array std_array{1, 2, 3}; - std::vector std_vector{1, 2, 3}; - Array array{1, 2, 3}; - ArrVec arrvec{1, 2, 3}; - Vector vector{1, 2, 3}; - - CHECK(init(std_array) == VectorView{data(std_array), length(std_array) - 1}); - CHECK(init(std_vector) == VectorView{data(std_vector), length(std_vector) - 1}); - CHECK(init(array) == VectorView{data(array), length(array) - 1}); - CHECK(init(arrvec) == VectorView{data(arrvec), length(arrvec) - 1}); - CHECK(init(vector) == VectorView{data(vector), length(vector) - 1}); - } -} - -TEST_CASE("last") -{ - auto std_array = std::array{1, 2, 3}; - auto std_vector = std::vector{1, 2, 3}; - auto array = Array{1, 2, 3}; - auto arrvec = ArrVec{1, 2, 3}; - auto vector = Vector{1, 2, 3}; - - CHECK(last(std_array) == 3); - CHECK(last(std_vector) == 3); - CHECK(last(array) == 3); - CHECK(last(arrvec) == 3); - CHECK(last(vector) == 3); -} - -TEST_CASE("take") -{ - SECTION("c array0") - { - const auto res = take(2, c_array_3); - CHECK(data(res) == data(c_array_3)); - CHECK(length(res) == 2); - CHECK(res[0] == 1.); - CHECK(res[1] == 2.); - } - - SECTION("c array1") - { - const auto res = take(-1, c_array_3); - CHECK(data(res) == data(c_array_3)); - CHECK(length(res) == 0); - } - - SECTION("c array2") - { - const auto res = take(9, c_array_3); - CHECK(data(res) == data(c_array_3)); - CHECK(length(res) == 3); - CHECK(res[0] == 1.); - CHECK(res[1] == 2.); - CHECK(res[2] == 3.); - } -} - -TEST_CASE("drop") -{ - SECTION("c array0") - { - const auto res = drop(2, c_array_3); - CHECK(data(res) == data(c_array_3) + 2); - CHECK(length(res) == 1); - CHECK(res[0] == 3.); - } - - SECTION("c array1") - { - const auto res = drop(-1, c_array_3); - CHECK(data(res) == data(c_array_3)); - CHECK(length(res) == 3); - } - - SECTION("c array2") - { - const auto res = drop(9, c_array_3); - CHECK(data(res) == end(c_array_3)); - CHECK(length(res) == 0); - } -} - -TEST_CASE("elem") -{ - SECTION("c array") - { - CHECK(elem(2., c_array_3) == true); - CHECK(elem(9., c_array_3) == false); - } - - SECTION("Array") - { - CHECK(elem(2., array_3) == true); - CHECK(elem(9., array_3) == false); - } - - SECTION("ArrayView") - { - CHECK(elem(2., array_view_3) == true); - CHECK(elem(9., array_view_3) == false); - } -} - -TEST_CASE("elem_index") -{ - SECTION("c array") - { - CHECK(elem_index(2., c_array_3).value() == 1); - CHECK(elem_index(9., c_array_3).is_nothing() == true); - } - - SECTION("Array") - { - CHECK(elem_index(2., array_3).value() == 1); - CHECK(elem_index(9., array_3).is_nothing() == true); - } - - SECTION("ArrayView") - { - CHECK(elem_index(2., array_view_3).value() == 1); - CHECK(elem_index(9., array_view_3).is_nothing() == true); - } -} - -TEST_CASE("elem_indices") -{ - SECTION("c array") - { - double c_array_3_[3] = {1., 2., 2.}; - CHECK(elem_indices(2., c_array_3_) == ArrVec{1, 2}); - CHECK(elem_indices(9., c_array_3_) == ArrVec{}); - } - - SECTION("Array") - { - double array_3_[3] = {1., 2., 2.}; - CHECK(elem_indices(2., array_3_) == ArrVec{1, 2}); - CHECK(elem_indices(9., array_3_) == ArrVec{}); - } - - SECTION("Vector") - { - Vector vector_3_ = {1, 2, 2}; - CHECK(elem_indices(2., vector_3_) == Vector{1, 2}); - CHECK(elem_indices(9., vector_3_) == Vector{}); - } -} - -TEST_CASE("find") -{ - auto is_two = [](double x) - { return x == 2. ? true : false; }; - - auto is_nine = [](double x) - { return x == 9. ? true : false; }; - - SECTION("c array") - { - CHECK(find(is_two, c_array_3) == true); - CHECK(find(is_nine, c_array_3) == false); - } - - SECTION("Array") - { - CHECK(find(is_two, array_3) == true); - CHECK(find(is_nine, array_3) == false); - } - - SECTION("ArrayView") - { - CHECK(find(is_two, array_view_3) == true); - CHECK(find(is_nine, array_view_3) == false); - } -} - -TEST_CASE("find_index") -{ - auto is_two = [](double x) - { return x == 2. ? true : false; }; - - auto is_nine = [](double x) - { return x == 9. ? true : false; }; - - SECTION("c array") - { - CHECK(find_index(is_two, c_array_3).value() == 1); - CHECK(find_index(is_nine, c_array_3).is_nothing() == true); - } - - SECTION("Array") - { - CHECK(find_index(is_two, array_3).value() == 1); - CHECK(find_index(is_nine, array_3).is_nothing() == true); - } - - SECTION("ArrayView") - { - CHECK(find_index(is_two, array_view_3).value() == 1); - CHECK(find_index(is_nine, array_view_3).is_nothing() == true); - } -} - -TEST_CASE("find_indices") -{ - auto is_two = [](double x) - { return x == 2. ? true : false; }; - - auto is_nine = [](double x) - { return x == 9. ? true : false; }; - - SECTION("c array") - { - double c_array_3_[3] = {1., 2., 2.}; - CHECK(find_indices(is_two, c_array_3_) == ArrVec{1, 2}); - CHECK(find_indices(is_nine, c_array_3_) == ArrVec{}); - } - - SECTION("Array") - { - double array_3_[3] = {1., 2., 2.}; - CHECK(find_indices(is_two, array_3_) == ArrVec{1, 2}); - CHECK(find_indices(is_nine, array_3_) == ArrVec{}); - } - - SECTION("Vector") - { - Vector vector_3_ = {1, 2, 2}; - CHECK(find_indices(is_two, vector_3_) == Vector{1, 2}); - CHECK(find_indices(is_nine, vector_3_) == Vector{}); - } -} - -#endif \ No newline at end of file diff --git a/test/sequence__test.hpp b/test/sequence__test.hpp deleted file mode 100644 index f3cb07c..0000000 --- a/test/sequence__test.hpp +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef SEQUENCE_TEST_HPP_ -#define SEQUENCE_TEST_HPP_ - -#include "efp.hpp" - -using namespace efp; - -TEST_CASE("initialization") -{ - SECTION("Array") - { - Array a{1, 2, 3}; - CHECK(a == Array{1, 2, 3}); - CHECK(a.size() == 3); - } - - SECTION("ArrVec") - { - ArrVec a = {1, 2, 3}; - - CHECK(a.size() == 3); - CHECK(a.capacity() == 4); - } - - SECTION("Vector") - { - Vector a = {0, 0, 0}; - for (int i = 0; i < a.size(); ++i) - { - a[i] = i + 1; - } - - Vector b = {1, 2, 3}; - - CHECK(a == b); - CHECK(a.size() == 3); - CHECK(b.size() == 3); - CHECK(a.capacity() == 3); - CHECK(b.capacity() == 3); - } -} - -Array array_rvo() -{ - return Array{1, 2, 3}; -}; - -Array array_nrvo() -{ - Array result{0, 0, 0}; - - result[0] = 1; - result[1] = 2; - result[2] = 3; - - return result; -}; - -ArrVec array_vector_rvo() -{ - return ArrVec{1, 2, 3}; -}; - -ArrVec array_vector_nrvo() -{ - ArrVec result{0, 0, 0}; - - result[0] = 1; - result[1] = 2; - result[2] = 3; - - return result; -}; - -Vector vector_rvo() -{ - return Vector{1, 2, 3}; -}; - -Vector vector_nrvo() -{ - Vector result{0, 0, 0}; - - result[0] = 1; - result[1] = 2; - result[2] = 3; - - return result; -}; - -TEST_CASE("copy elision") -{ - SECTION("Array") - { - CHECK(Array{1, 2, 3} == array_rvo()); - CHECK(Array{1, 2, 3} == array_nrvo()); - } - - SECTION("ArrVec") - { - CHECK(ArrVec{1, 2, 3} == array_vector_rvo()); - CHECK(ArrVec{1, 2, 3} == array_vector_nrvo()); - } - - SECTION("Vector") - { - CHECK(Vector{1, 2, 3} == vector_rvo()); - CHECK(Vector{1, 2, 3} == vector_nrvo()); - } -} - -TEST_CASE("assignment") -{ - SECTION("Array") - { - Array a{1., 2., 3.}; - Array b; - - b = a; - CHECK(a == b); - } - - SECTION("ArrVec") - { - ArrVec a{1., 2., 3.}; - ArrVec b; - - b = a; - CHECK(a == b); - } - - SECTION("Vector") - { - Vector a{1., 2., 3.}; - Vector b; - - b = a; - CHECK(a == b); - } -} - -TEST_CASE("ArrayView") -{ - SECTION("construction") - { - int a = 0; - const int a_const = 0; - - // const pointer will create read-only view. - - ArrayView a_view0{&a}; - ArrayView a_view1{&a_const}; - const ArrayView a_view2{&a}; - const ArrayView a_view3{&a_const}; - // ArrayView a_view4{&a_const}; - ArrayView a_view5{&a}; - // const ArrayView a_view6{&a_const}; - const ArrayView a_view7{&a}; - } - - SECTION("copy construction") - { - ArrayView view_1{data(array_3)}; - auto view_2 = view_1; - CHECK(view_1 == view_2); - } -} - -TEST_CASE("VectorView") -{ - SECTION("copy construction") - { - VectorView view_1{data(array_3), 3}; - auto view_2 = view_1; - CHECK(view_1 == view_2); - } -} - -TEST_CASE("Element_t") -{ - CHECK(IsSame>::value == true); - // Element_t is not catching const of container. - CHECK(IsSame>::value == false); -} - -#endif \ No newline at end of file