Created
April 27, 2017 05:37
-
-
Save mythagel/2d87ebb861e3cd0019a6dfc2545311a9 to your computer and use it in GitHub Desktop.
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 <cstdint> | |
#include <cstdio> | |
#include <stdexcept> | |
#include <vector> | |
// C compatible external api | |
extern "C" { | |
// Input / Output value types | |
enum { | |
tagFeedrate = 'feed', | |
tagSpindleSpeed = 'sspd', | |
tagCutterTeeth = 'ctth', | |
tagFeedPerTooth = 'fpth', | |
}; | |
// Input / Output tagged value | |
struct TaggedValue { | |
unsigned tag; | |
double value; | |
}; | |
// TODO entry point function | |
// void calculate(TaggedValue* x, unsigned n, ...); | |
} | |
// Implementation | |
// Introduce distinct types for value type enumeration | |
template <unsigned TAG> | |
struct Tag { | |
static constexpr unsigned value = TAG; | |
}; | |
// A list of the above tag types | |
template <typename...Tags> | |
struct TagList { }; | |
// Uses parameter pack to find arguments for function and call from generic list of parameters. | |
template <typename OUT, typename...IN> | |
struct TaggedFn { | |
static unsigned out() { | |
return OUT::value; | |
} | |
template<typename Arg, typename... Args> | |
static bool all_of(Arg arg, Args... args) { return arg && all_of(args...); } | |
static bool all_of(bool arg) { return arg; } | |
static bool has_in(TaggedValue* params, unsigned n) { | |
auto contains = [params, n](unsigned tag) { | |
for (unsigned i = 0; i < n; ++i) | |
if (params[i].tag == tag) | |
return true; | |
return false; | |
}; | |
return all_of(contains(IN::value)...); | |
} | |
template <typename Fn> | |
static double call(Fn fn, TaggedValue* params, unsigned n) { | |
auto get = [params, n](unsigned tag) { | |
for (unsigned i = 0; i < n; ++i) | |
if (params[i].tag == tag) | |
return params[i].value; | |
throw std::logic_error("Required input tag not present."); | |
}; | |
return fn(get(IN::value)...); | |
} | |
}; | |
// Helpers to expand TagList back to parameter pack | |
// base case | |
template <typename OUT, typename...IN> | |
struct TagFunction { | |
using type = TaggedFn<OUT, IN...>; | |
}; | |
// specialisation for TagList | |
template <typename OUT, typename...IN> | |
struct TagFunction<OUT, TagList<IN...>> { | |
using type = typename TagFunction<OUT, IN...>::type; | |
}; | |
// List of defined feedrate functions | |
enum class Functions { | |
fz | |
}; | |
template <Functions FunctionTag> | |
struct traits {}; | |
template <unsigned TAGOUT, unsigned... TAGIN> | |
struct traits_helper { | |
using OUT = Tag<TAGOUT>; | |
using IN = TagList<Tag<TAGIN>...>; | |
}; | |
// Generic interface type for feedrate functions | |
template<Functions FunctionTag> | |
struct Function { | |
using type = typename TagFunction<typename traits<FunctionTag>::OUT, typename traits<FunctionTag>::IN>::type; | |
static unsigned out() { | |
return type::out(); | |
} | |
static bool has_in(TaggedValue* params, unsigned n) { | |
return type::has_in(params, n); | |
} | |
static double call(TaggedValue* x, unsigned n) { | |
return type::template call<>(traits<FunctionTag>::fn, x, n); | |
} | |
}; | |
// fz function | |
template <> | |
struct traits <Functions::fz> : traits_helper<tagFeedPerTooth, tagFeedrate, tagSpindleSpeed, tagCutterTeeth> { | |
static double fn(double Vf, double n, unsigned Zc) { | |
return Vf / (n * Zc); | |
} | |
}; | |
int main() { | |
std::vector<TaggedValue> in = { | |
{tagSpindleSpeed, 3000}, | |
{tagFeedrate, 400}, | |
{tagCutterTeeth, 4} | |
}; | |
std::vector<TaggedValue> out = { | |
{tagFeedPerTooth, 0} | |
}; | |
if (Function<Functions::fz>::has_in(in.data(), in.size())) { | |
auto v = Function<Functions::fz>::call(in.data(), in.size()); | |
fprintf(stderr, "%f\n", v); | |
} else { | |
fprintf(stderr, "Input parameters missing.\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment