add range adaptors (filter, transform)

This commit is contained in:
Christopher Lackner 2020-09-19 17:39:03 +02:00
parent 283db5c637
commit 1666155d25
4 changed files with 129 additions and 1 deletions

View File

@ -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)

109
libsrc/core/ranges.hpp Normal file
View File

@ -0,0 +1,109 @@
#ifndef NETGEN_CORE_RANGES_HPP
#define NETGEN_CORE_RANGES_HPP
#include <iterator>
namespace ngcore
{
template<typename Iterator>
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<typename FUNC>
class FilterAdapter
{
FUNC f;
public:
FilterAdapter(FUNC af) : f(af) { ; }
FUNC GetFunction() const { return f; }
};
template<typename FUNC, typename Iterator>
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<typename FUNC>
FilterAdapter<FUNC> filter(FUNC f) { return {f}; }
template<typename Range, typename FUNC>
auto operator |(Range&& range, FilterAdapter<FUNC> adapter)
-> AdapterRange<FilterIterator<FUNC,decltype(std::begin(range))>>
{
return {{adapter.GetFunction(),std::begin(range),std::end(range)},
{adapter.GetFunction(), std::end(range), std::end(range)}};
}
template<typename FUNC, typename Iterator>
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<typename FUNC>
class TransformAdapter
{
FUNC f;
public:
TransformAdapter(FUNC af) : f(af) { ; }
FUNC GetFunction() const { return f; }
};
template<typename FUNC>
TransformAdapter<FUNC> transform(FUNC f) { return {f}; }
template<typename Range, typename FUNC>
auto operator |(Range&& range, TransformAdapter<FUNC> adapter)
-> AdapterRange<TransformIterator<FUNC,decltype(std::begin(range))>>
{
return {{adapter.GetFunction(), std::begin(range)},
{adapter.GetFunction(),std::end(range)}};
}
} // namespace ngcore
#endif // NETGEN_CORE_RANGES_HPP

View File

@ -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)

18
tests/catch/ranges.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "catch.hpp"
#include <core/array.hpp>
#include <core/ranges.hpp>
using namespace ngcore;
TEST_CASE("ranges")
{
Array<int> a { 3, -1, 10, -5 };
Array<int> positive { 3, 10 };
int i = 0;
for(auto pos_val : a | filter([](auto val) { return val >= 0; }))
{
CHECK(pos_val == positive[i++]);
}
}