Created
December 23, 2016 03:02
-
-
Save rroohhh/3309f1bec984f8e83be3e9d3aea70308 to your computer and use it in GitHub Desktop.
create functions that are callable with string arrays
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 <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