Browse Source

Odd operator overload composing functions and vectors

main
andpal@linlap 4 years ago
parent
commit
537891a43e
  1. 26
      f-composition/Makefile
  2. 116
      f-composition/functional.hpp
  3. 29
      f-composition/main.cpp
  4. 26
      f-composition/pretty_print.hpp

26
f-composition/Makefile

@ -0,0 +1,26 @@
EXE=a.out
CC=clang++
DEBUG?=0
CFLAGS=-O2 -std=c++20 -Wall -Wextra -D DEBUG=$(DEBUG)
.PHONY: all clean test
test:
- @rm $(EXE)
$(CC) $(CFLAGS) -o $(EXE) main.cpp
./$(EXE)
all: $(EXE)
clean:
rm -rf $(EXE) ./*.out ./*.gch
$(EXE): main.cpp pretty_print.hpp.gch functional.hpp.gch
$(CC) $(CFLAGS) -o $(EXE) main.cpp
functional.hpp.gch: functional.hpp
$(CC) $(CFLAGS) -c functional.hpp
pretty_print.hpp.gch: pretty_print.hpp
$(CC) $(CFLAGS) -c pretty_print.hpp

116
f-composition/functional.hpp

@ -0,0 +1,116 @@
#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

29
f-composition/main.cpp

@ -0,0 +1,29 @@
#include <iostream>
#include <typeinfo>
#include <stdint.h>
#include <vector>
#include "functional.hpp" // (f * g)(t) == f(g(t))
#include "pretty_print.hpp" // ostream << vector
int main()
{
std::vector<int> const vec{1,2,3,4,5};
auto const dec = [](int const& v) {
return v-1;
};
auto const sq = [](int const& v) {
return v*v;
};
std::vector<int> const transformed_vec{ dec * sq * vec };
std::cout << "Orig: \t" << vec << '\n';
std::cout << "Sq: \t" << sq * vec << '\n';
std::cout << "Sq-1: \t" << transformed_vec << "\n\n";
std::cout << "Const:\t" << sq*dec*7 << std::endl;
}

26
f-composition/pretty_print.hpp

@ -0,0 +1,26 @@
#ifndef PRETTY_PRINT_H
#define PRETTY_PRINT_H
#include <iostream>
#include <iomanip>
#include <vector>
template<typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& vec)
{
if (vec.size() == 0) { return os; } // Empty
os << "[" << vec[0]; // First
if (1 < vec.size()) { // Rest
for (auto it = ++vec.cbegin(); it != vec.cend(); ++it) {
os << ", " << std::setw(2) << *it;
}
}
os << "]";
return os;
}
#endif
Loading…
Cancel
Save