You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.6 KiB
116 lines
2.6 KiB
#ifndef FUNCTIONAL_H
|
|
#define FUNCTIONAL_H
|
|
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <utility>
|
|
|
|
/*
|
|
* Composition of functions through operator*
|
|
*
|
|
* Immediate evaluation of <lambda> * <rvalue>
|
|
*/
|
|
template<typename F, typename G>
|
|
auto composition_h(F&& f, G&& g, std::true_type) {
|
|
#if DEBUG==1
|
|
std::cout << "<Lambda> * <Lambda> -> <Lambda>" << std::endl; // DEBLURG
|
|
#endif
|
|
return [f, g](auto&& t){
|
|
return f( g( std::forward<decltype(t)>(t) ) );
|
|
};
|
|
}
|
|
|
|
template<typename F, typename G>
|
|
auto composition_h(F&& f, G&& g, std::false_type) {
|
|
#if DEBUG==1
|
|
std::cout << "<Lambda> * T -> T" << std::endl; // DEBLURG
|
|
#endif
|
|
return f( g );
|
|
}
|
|
|
|
template<typename F, typename G>
|
|
auto operator*(F&& f, G&& g) {
|
|
#if DEBUG==1
|
|
std::cout << "f * g -> ";
|
|
#endif
|
|
return composition_h(f, g, std::is_lvalue_reference<G&&>());
|
|
}
|
|
|
|
|
|
/*
|
|
* Following templates handle mapping of transforming function
|
|
* onto vector<T> types
|
|
*/
|
|
template<typename Transform, typename T>
|
|
auto operator*(Transform&& transform, std::vector<T> const& vec) {
|
|
#if DEBUG==1
|
|
std::cout << "<Lambda> * vec<T> -> vec<T> \t[const]" << std::endl; // DEBLURG
|
|
#endif
|
|
std::vector<T> transformed_vec;
|
|
transformed_vec.reserve( vec.size() );
|
|
|
|
for (auto const& v : vec) {
|
|
transformed_vec.push_back( transform(v) );
|
|
}
|
|
|
|
return transformed_vec;
|
|
}
|
|
|
|
template<typename Transform, typename T>
|
|
auto operator*(Transform&& transform, std::vector<T>&& vec) {
|
|
#if DEBUG==1
|
|
std::cout << "<Lambda> * vec<T> -> vec<T> \t[rvalue]" << std::endl; // DEBLURG
|
|
#endif
|
|
std::vector<T> transformed_vec;
|
|
transformed_vec.reserve( vec.size() );
|
|
|
|
for (auto const& v : vec) {
|
|
transformed_vec.push_back( transform(v) );
|
|
}
|
|
|
|
return transformed_vec;
|
|
}
|
|
|
|
template<typename Transform, typename T>
|
|
auto operator*(Transform&& transform, std::vector<T>& vec) {
|
|
#if DEBUG==1
|
|
std::cout << "<Lambda> * vec<T> -> vec<T> \t[non-const]" << std::endl;
|
|
#endif
|
|
|
|
std::vector<T> transformed_vec;
|
|
transformed_vec.reserve( vec.size() );
|
|
|
|
for (auto const& v : vec) {
|
|
transformed_vec.push_back( transform(v) );
|
|
}
|
|
|
|
return transformed_vec;
|
|
}
|
|
|
|
|
|
auto const id = [](auto&& t) -> decltype(t)&& {
|
|
return std::forward<decltype(t)>(t);
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* Maps a transform function onto each element in vector<T>
|
|
*
|
|
* Obsolete
|
|
*/
|
|
template<typename F, typename T>
|
|
auto map = [](F&& transform) {
|
|
return [transform](std::vector<T> const& vec) {
|
|
std::vector<T> transformed_vec;
|
|
transformed_vec.reserve( vec.size() );
|
|
for (auto const& v : vec) {
|
|
transformed_vec.push_back( transform(v) );
|
|
}
|
|
return transformed_vec;
|
|
};
|
|
};
|
|
|
|
|
|
#endif
|