Created
April 3, 2020 18:25
-
-
Save leopoldcambier/31fdb4308c22dd18775f64a740ac35ba to your computer and use it in GitHub Desktop.
Chaining functions using C++ template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<tuple> | |
#include<iostream> | |
#include<string> | |
template<typename Tin, typename Tout> | |
struct transformer { | |
Tout transform(Tin tin) { | |
std::cout << "Hi!\n"; | |
return tin + 1; | |
} | |
using Tin_type = Tin; | |
using Tout_type = Tout; | |
}; | |
// Returns the Tin of the first element | |
template<typename... Trs> | |
struct Tin_list | |
{ | |
using type = typename std::tuple_element<0, std::tuple<Trs...>>::type::Tin_type; | |
}; | |
// Returns the Tout of the last element | |
template<typename... Trs> | |
struct Tout_list | |
{ | |
using type = typename std::tuple_element<sizeof...(Trs)-1, std::tuple<Trs...>>::type::Tout_type; | |
}; | |
// Base case; only one transformator | |
template<typename Tr> | |
typename Tr::Tout_type chain_transform(typename Tr::Tin_type tin, Tr transformer) | |
{ | |
return transformer.transform(tin); | |
} | |
// Recursive case | |
// enable_if will enable this function if Trs... has only one element. Otherwise it will call the above base case | |
template<typename Tr, typename... Trs> | |
typename std::enable_if<(sizeof...(Trs) > 0), typename Tout_list<Tr,Trs...>::type>::type | |
chain_transform(typename Tin_list<Tr,Trs...>::type tin, Tr transformer, Trs... transformers) | |
{ | |
auto out = transformer.transform(tin); | |
return chain_transform(out, transformers...); | |
} | |
struct transformer_0 { | |
std::string transform(int i) { | |
return "coucou" + std::to_string(i); | |
} | |
using Tin_type = int; | |
using Tout_type = std::string; | |
}; | |
struct transformer_1 { | |
double transform(std::string s) { | |
return (double) s.size(); | |
} | |
using Tin_type = std::string; | |
using Tout_type = double; | |
}; | |
struct transformer_2 { | |
size_t transform(double v) { | |
return (size_t)v + 123; | |
} | |
using Tin_type = double; | |
using Tout_type = size_t; | |
}; | |
int main() { | |
auto t0 = transformer_0(); | |
auto t1 = transformer_1(); | |
auto t2 = transformer_2(); | |
std::cout << chain_transform(145, t0, t1, t2) << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment