From 1666155d25de9bf0222f9a1e3fde350909b62aff Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Sat, 19 Sep 2020 17:39:03 +0200 Subject: [PATCH] add range adaptors (filter, transform) --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/ranges.hpp | 109 +++++++++++++++++++++++++++++++++++++ tests/catch/CMakeLists.txt | 1 + tests/catch/ranges.cpp | 18 ++++++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 libsrc/core/ranges.hpp create mode 100644 tests/catch/ranges.cpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 16c43a82..a2873ed9 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -65,7 +65,7 @@ target_link_libraries(ngcore PUBLIC netgen_mpi PRIVATE netgen_python ${CMAKE_THR install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.hpp array.hpp taskmanager.hpp concurrentqueue.h localheap.hpp python_ngcore.hpp flags.hpp - xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp + xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/ranges.hpp b/libsrc/core/ranges.hpp new file mode 100644 index 00000000..658ee3d0 --- /dev/null +++ b/libsrc/core/ranges.hpp @@ -0,0 +1,109 @@ +#ifndef NETGEN_CORE_RANGES_HPP +#define NETGEN_CORE_RANGES_HPP + +#include + +namespace ngcore +{ + template + class AdapterRange + { + Iterator _begin,_end; + public: + AdapterRange(Iterator abegin, Iterator aend) : _begin(abegin), _end(aend) { ; } + Iterator begin() const { return _begin; } + Iterator end() const { return _end; } + }; + + template + class FilterAdapter + { + FUNC f; + public: + FilterAdapter(FUNC af) : f(af) { ; } + FUNC GetFunction() const { return f; } + }; + + template + class FilterIterator + { + Iterator iter; + Iterator end; + FUNC f; + public: + FilterIterator(FUNC af, Iterator aiter, Iterator aend) + : f(af), iter(aiter), end(aend) + { + while(iter!=end && !f(*iter)) + ++iter; + } + inline FilterIterator& operator ++() + { + ++iter; + while(iter!=end && !f(*iter)) + ++iter; + return *this; + } + + inline bool operator !=(FilterIterator other) + { + return iter != other.iter; + } + + inline bool operator ==(FilterIterator other) + { + return iter == other.iter; + } + + inline decltype(auto) operator *() const + { + return *iter; + } + }; + + template + FilterAdapter filter(FUNC f) { return {f}; } + + template + auto operator |(Range&& range, FilterAdapter adapter) + -> AdapterRange> + { + return {{adapter.GetFunction(),std::begin(range),std::end(range)}, + {adapter.GetFunction(), std::end(range), std::end(range)}}; + } + + template + class TransformIterator + { + FUNC f; + Iterator iter; + public: + TransformIterator(FUNC af, Iterator aiter) : f(af), iter(aiter) { ; } + + TransformIterator& operator++() { ++iter; } + bool operator !=(TransformIterator other) { return iter != other.iter; } + decltype(auto) operator *() const { return f(*iter); } + }; + + template + class TransformAdapter + { + FUNC f; + public: + TransformAdapter(FUNC af) : f(af) { ; } + FUNC GetFunction() const { return f; } + }; + + template + TransformAdapter transform(FUNC f) { return {f}; } + + template + auto operator |(Range&& range, TransformAdapter adapter) + -> AdapterRange> + { + return {{adapter.GetFunction(), std::begin(range)}, + {adapter.GetFunction(),std::end(range)}}; + } +} // namespace ngcore + +#endif // NETGEN_CORE_RANGES_HPP diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index c3a6525d..12a665df 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -27,6 +27,7 @@ endmacro() add_unit_test(archive archive.cpp) add_unit_test(array array.cpp) +add_unit_test(ranges ranges.cpp) add_unit_test(symboltable symboltable.cpp) add_unit_test(utils utils.cpp) add_unit_test(version version.cpp) diff --git a/tests/catch/ranges.cpp b/tests/catch/ranges.cpp new file mode 100644 index 00000000..b4559de0 --- /dev/null +++ b/tests/catch/ranges.cpp @@ -0,0 +1,18 @@ + +#include "catch.hpp" + +#include +#include + +using namespace ngcore; + +TEST_CASE("ranges") +{ + Array a { 3, -1, 10, -5 }; + Array positive { 3, 10 }; + int i = 0; + for(auto pos_val : a | filter([](auto val) { return val >= 0; })) + { + CHECK(pos_val == positive[i++]); + } +}