From 537891a43e88407719dc290e6725180139053a55 Mon Sep 17 00:00:00 2001 From: "andpal@linlap" Date: Sun, 27 Feb 2022 22:14:16 +0100 Subject: [PATCH] Odd operator overload composing functions and vectors --- f-composition/Makefile | 26 ++++++++ f-composition/functional.hpp | 116 +++++++++++++++++++++++++++++++++ f-composition/main.cpp | 29 +++++++++ f-composition/pretty_print.hpp | 26 ++++++++ 4 files changed, 197 insertions(+) create mode 100755 f-composition/Makefile create mode 100644 f-composition/functional.hpp create mode 100644 f-composition/main.cpp create mode 100644 f-composition/pretty_print.hpp diff --git a/f-composition/Makefile b/f-composition/Makefile new file mode 100755 index 0000000..bc2273b --- /dev/null +++ b/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 + diff --git a/f-composition/functional.hpp b/f-composition/functional.hpp new file mode 100644 index 0000000..2f0fd11 --- /dev/null +++ b/f-composition/functional.hpp @@ -0,0 +1,116 @@ +#ifndef FUNCTIONAL_H +#define FUNCTIONAL_H + + +#include +#include +#include + +/* + * Composition of functions through operator* + * + * Immediate evaluation of * + */ +template +auto composition_h(F&& f, G&& g, std::true_type) { +#if DEBUG==1 + std::cout << " * -> " << std::endl; // DEBLURG +#endif + return [f, g](auto&& t){ + return f( g( std::forward(t) ) ); + }; +} + +template +auto composition_h(F&& f, G&& g, std::false_type) { +#if DEBUG==1 + std::cout << " * T -> T" << std::endl; // DEBLURG +#endif + return f( g ); +} + +template +auto operator*(F&& f, G&& g) { +#if DEBUG==1 + std::cout << "f * g -> "; +#endif + return composition_h(f, g, std::is_lvalue_reference()); +} + + +/* + * Following templates handle mapping of transforming function + * onto vector types + */ +template +auto operator*(Transform&& transform, std::vector const& vec) { +#if DEBUG==1 + std::cout << " * vec -> vec \t[const]" << std::endl; // DEBLURG +#endif + std::vector transformed_vec; + transformed_vec.reserve( vec.size() ); + + for (auto const& v : vec) { + transformed_vec.push_back( transform(v) ); + } + + return transformed_vec; +} + +template +auto operator*(Transform&& transform, std::vector&& vec) { +#if DEBUG==1 + std::cout << " * vec -> vec \t[rvalue]" << std::endl; // DEBLURG +#endif + std::vector transformed_vec; + transformed_vec.reserve( vec.size() ); + + for (auto const& v : vec) { + transformed_vec.push_back( transform(v) ); + } + + return transformed_vec; +} + +template +auto operator*(Transform&& transform, std::vector& vec) { +#if DEBUG==1 + std::cout << " * vec -> vec \t[non-const]" << std::endl; +#endif + + std::vector 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(t); +}; + + + +/* + * Maps a transform function onto each element in vector + * + * Obsolete + */ +template +auto map = [](F&& transform) { + return [transform](std::vector const& vec) { + std::vector transformed_vec; + transformed_vec.reserve( vec.size() ); + for (auto const& v : vec) { + transformed_vec.push_back( transform(v) ); + } + return transformed_vec; + }; +}; + + +#endif diff --git a/f-composition/main.cpp b/f-composition/main.cpp new file mode 100644 index 0000000..ab400aa --- /dev/null +++ b/f-composition/main.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include + + +#include "functional.hpp" // (f * g)(t) == f(g(t)) +#include "pretty_print.hpp" // ostream << vector + + +int main() +{ + std::vector 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 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; +} diff --git a/f-composition/pretty_print.hpp b/f-composition/pretty_print.hpp new file mode 100644 index 0000000..9975927 --- /dev/null +++ b/f-composition/pretty_print.hpp @@ -0,0 +1,26 @@ +#ifndef PRETTY_PRINT_H +#define PRETTY_PRINT_H + +#include +#include +#include + +template +std::ostream& operator<<(std::ostream& os, std::vector 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