1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
#include <array>
#include <iostream>
#include <tuple>
#include <functional>
#include <map>
struct myvariant
{
int type;
union value {
int ival;
double dval;
};
value val;
myvariant() { type = 0; val.ival = 0; }
myvariant(int a) {
type = 0;
val.ival = a;
}
myvariant(double d) { type = 1; val.dval = d; }
};
template <typename ReturnType, typename... Args> struct base_traits {
using return_type = ReturnType;
using function = const std::function<ReturnType(Args...)>;
static size_t constexpr arity = sizeof ... (Args);
};
template <typename Function> struct function_traits;
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType(Args...)> : public base_traits<ReturnType, Args...> {};
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType(&)(Args...)> : public base_traits<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> : public base_traits<ReturnType, Args...> {};
template <typename ReturnType, typename... Args>
struct function_traits<std::function<ReturnType(Args...)>> : public base_traits<ReturnType, Args...> {};
template<typename T>
auto make_function(T const& f) ->
typename std::enable_if<std::is_function<T>::value && !std::is_bind_expression<T>::value, std::function<T>>::type
{ return f; }
template<typename T>
auto make_function(T const& f) ->
typename std::enable_if<
!std::is_function<T>::value && !std::is_bind_expression<T>::value,
typename function_traits<decltype(&T::operator())>::function>::type
{ return static_cast<typename function_traits<decltype(&T::operator())>::function>(f); }
template<typename T>
struct variant_value {
};
template<>
struct variant_value<myvariant const&> {
static myvariant const& value(myvariant const& item) { return item; }
};
template<>
struct variant_value<int> {
static int value(myvariant const& item) { return item.val.ival; }
};
template<>
struct variant_value<double> {
static double value(myvariant const& item) { return item.val.dval; }
};
std::pair<bool, std::map<std::string,myvariant>::const_iterator> check_arg(std::string name, int typeIndex, std::map<std::string,myvariant> const& parameters)
{
auto it = parameters.find(name);
if(it != parameters.end())
{
if(it->second.type == typeIndex)
return std::make_pair(true, it);
else
return std::make_pair(false, parameters.end());
}
else
return std::make_pair(false, it);
}
template<typename T>
struct type_index
{
};
template<>
struct type_index<int>
{
static constexpr const int value = 0;
};
template<>
struct type_index<double>
{
static constexpr const int value = 1;
};
template<const int n, typename... FuncArgs>
struct function_invoker
{
template<typename Array, typename Fun, typename... Args>
static auto call(Fun fun, Array const& arr, std::map<std::string,myvariant> const& parameters, Args... arg) ->
decltype(function_invoker<n-1, FuncArgs...>::call(fun, arr, parameters, variant_value< typename std::tuple_element<n-1, std::tuple<FuncArgs...> >::type >::value(myvariant(0)), arg...))
{
typedef typename std::tuple_element<n-1, std::tuple<FuncArgs...> >::type itemType;
auto result = check_arg(std::get<n-1>(arr), type_index<itemType>::value, parameters);
if(!result.first)
{
std::cerr << "arg error" << std::endl;
return -1; // -1 is error;
}
else
return function_invoker<n-1, FuncArgs...>::call(fun, arr, parameters, variant_value<itemType>::value(result.second->second), arg...);
}
};
template<typename... FuncArgs>
struct function_invoker<0, FuncArgs...>
{
template<typename Array, typename Fun, typename... Args>
static auto call(Fun fun, Array /*arr*/, std::map<std::string,myvariant> const& /*parameters*/, Args... arg) -> decltype(fun(arg...))
{
return fun(arg...);
}
};
template<typename Array, typename... Args>
std::function<int(std::map<std::string,myvariant> const&)> createFunction2(Array const& paramDescription, std::function<int(Args...)> func)
{
return [func, paramDescription]
(std::map<std::string,myvariant> const& parameters)
{
return function_invoker<sizeof...(Args), Args...>::call(func, paramDescription, parameters);
};
}
template<typename Array, typename Fun>
std::function<int(std::map<std::string, myvariant>)> createFunction(Array const& paramDescription, Fun fun)
{
auto f = make_function(fun);
return createFunction2(paramDescription, f);
}
int sum1(int a, int b, int c, int d, int e, int f, double dv)
{
std::cerr << a << " " << b << " " << c << " " << d << " " << e << " " << f << " " << dv << std::endl;
return a + b + c + d + e + f;
}
int main()
{
std::array<std::string, 7> desc = {{"first","second","third","fourth", "fifth","sixth", "double"}};
std::map<std::string, myvariant> args;
// auto fun = createFunction(desc, sum1); not working, strange...
auto f2 = make_function(sum1);
auto fun = createFunction(desc, f2);
std::cerr << fun(args) << std::endl;
args = {{"first", 1}, {"second", 2}, {"third", 3}, {"fifth", 5}, {"fourth", 4},{"sixth", 6},{"double", 4.3}};
std::cerr << fun(args) << std::endl;
args["first"].type = 1;
args["first"].val.dval = 2.3;
std::cerr << fun(args) << std::endl;
return 0;
} |
Partager