Skip to content

Instantly share code, notes, and snippets.

@rroohhh
Created December 23, 2016 03:02
Show Gist options
  • Save rroohhh/3309f1bec984f8e83be3e9d3aea70308 to your computer and use it in GitHub Desktop.
Save rroohhh/3309f1bec984f8e83be3e9d3aea70308 to your computer and use it in GitHub Desktop.
create functions that are callable with string arrays
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
#include <vector>
#include <functional>
#include <cassert>
using namespace std;
// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) > {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
// for function pointers
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType (*)(Args...)> {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
template <typename L>
static typename function_traits<L>::f_type make_function(L l){
return (typename function_traits<L>::f_type)(l);
}
//handles bind & multiple function call operator()'s
template<typename ReturnType, typename... Args, class T>
auto make_function(T&& t)
-> std::function<decltype(ReturnType(t(std::declval<Args>()...)))(Args...)>
{return {std::forward<T>(t)};}
//handles explicit overloads
template<typename ReturnType, typename... Args>
auto make_function(ReturnType(*p)(Args...))
-> std::function<ReturnType(Args...)> {
return {p};
}
//handles explicit overloads
template<typename ReturnType, typename... Args, typename ClassType>
auto make_function(ReturnType(ClassType::*p)(Args...))
-> std::function<ReturnType(Args...)> {
return {p};
}
struct pass {
template<typename ...T> pass(T...) {}
};
namespace detail {
template<template<typename> class F, typename... Args, typename T, size_t... S>
tuple<Args...> to_tuple(const vector<T> & v, index_sequence<S...>) {
return make_tuple((F<Args>()(v[S]))...);
}
}
template<template<typename> class F, typename... Args, typename T>
tuple<Args...> to_tuple(const vector<T> & v) {
assert(v.size() >= sizeof...(Args));
return detail::to_tuple<F, Args...>(v, index_sequence_for<Args...>());
}
template<template<typename> class F, typename... Args, typename T>
void test(T value) {
using swallow = int[];
(void) swallow{0, void(F<Args>()(value), 1)...};
}
template<typename T>
struct parse_string {
T operator()(string value) {
stringstream ss(value);
T ret;
ss >> ret;
return ret;
}
};
namespace detail {
template<typename... Args, size_t... S>
ostream & print_tuple(ostream & os, tuple<Args...> t, index_sequence<S...>) {
using swallow = int[];
(void) swallow{0, (void(os << (S == 0 ? "" : ", ") << get<S>(t)), 1)...};
}
}
template<typename... Args>
ostream & operator<<(ostream & os, tuple<Args...> t) {
os << "(";
detail::print_tuple(os, t, index_sequence_for<Args...>());
return os << ")";
}
namespace detail {
template<typename F, typename... Args, size_t... S>
auto apply_to_fun(F fun, tuple<Args...> t, index_sequence<S...>) {
return fun(get<S>(t)...);
}
}
template<typename F, typename... Args>
auto apply_to_fun(F fun, tuple<Args...> t) {
return detail::apply_to_fun(fun, t, index_sequence_for<Args...>());
}
double test_fun(int i, double d) {
cout << "double " << d << endl;
cout << "int " << i << endl;
return i + d;
}
template<typename... Args, typename T>
auto cmd_fun(function<T(Args...)> f) {
return [=](vector<string> s){
return apply_to_fun(f, to_tuple<parse_string, Args...>(s));
};
}
void no_arg() {
cout << "got called" << endl;
}
int main() {
// cout << t(make_function(test_fun)) << endl;
cmd_fun(make_function(no_arg))({{"1"}, {"1.4"}});
cout << cmd_fun(make_function(test_fun))({{"1"}, {"1.4"}}) << endl;
// cout << to_tuple<parse_string, int, double>(vector<string>{{"1"}, {"1.4"}}) << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment