Skip to content

Instantly share code, notes, and snippets.

@IceN9ne
Created March 21, 2017 06:33
Show Gist options
  • Save IceN9ne/dd83626dc8fd5a178c6270145cab4169 to your computer and use it in GitHub Desktop.
Save IceN9ne/dd83626dc8fd5a178c6270145cab4169 to your computer and use it in GitHub Desktop.
A Genetic Programming test data structure
#include <tuple>
template <typename T>
struct Node
{
virtual T operator()(const std::tuple<T,T,T>& params) = 0;
};
template <typename T, T(*f)(const std::tuple<T,T,T>&)>
struct TermNode : Node<T>
{
T operator()(const std::tuple<T,T,T>& params) override { return f(params); }
};
template <typename T, T(*f)(const T&)>
struct UnNode : Node<T>
{
UnNode(Node<T> *c) : child{c} {}
T operator()(const std::tuple<T,T,T>& params) override { return f((*child)(params)); }
Node<T> *child = nullptr;
};
template <typename T, T(*f)(const T&, const T&)>
struct BinNode : Node<T>
{
BinNode(Node<T> *l, Node<T> *r) : left{l}, right{r} {}
T operator()(const std::tuple<T,T,T>& params) override { return f((*left)(params), (*right)(params)); }
Node<T> *left = nullptr;
Node<T> *right = nullptr;
};
template <typename T>
using Neg = UnNode<T, [](const T& val){ return -val; }>;
template <typename T>
using Add = BinNode<T, [](const T& lhs, const T& rhs){ return lhs + rhs; }>;
template <typename T>
using Sub = BinNode<T, [](const T& lhs, const T& rhs){ return lhs - rhs; }>;
template <typename T>
using Mul = BinNode<T, [](const T& lhs, const T& rhs){ return lhs * rhs; }>;
template <typename T>
using Div = BinNode<T, [](const T& lhs, const T& rhs){ return lhs / rhs; }>;
template <typename T>
using Mod = BinNode<T, [](const T& lhs, const T& rhs){ return lhs % rhs; }>;
template <typename T>
using X = TermNode<T, [](const std::tuple<T,T,T>& params){ return std::get<0>(params); }>;
template <typename T>
using Y = TermNode<T, [](const std::tuple<T,T,T>& params){ return std::get<1>(params); }>;
template <typename T>
using Z = TermNode<T, [](const std::tuple<T,T,T>& params){ return std::get<2>(params); }>;
int main(int argc, char *argv[])
{
int x{1}, y{2}, z{3};
// Clang can optimize this
X<int> nodeX;
Y<int> nodeY;
Z<int> nodeZ;
Neg<int> nodeNeg{&nodeZ};
Add<int> nodeAdd{&nodeX, &nodeY};
Sub<int> nodeSub{&nodeAdd, &nodeNeg};
return nodeSub(std::make_tuple(x, y, z));
/*
// But it can't optimize this
Node<int> *root = new Sub<int>{new Add<int>{new X<int>, new Y<int>}, new Neg<int>{new Z<int>}};
return (*root)(std::make_tuple(x, y, z));
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment