Say i have the following scenario:
namespace detail
{
using duk_c_function_t = std::function<duk_ret_t(duk_context*)>;
template<typename T_Return(typename ... T_Params), std::function<T_Return(T_Params)>
duk_ret_t duk_function_proxy(duk_context* ctx)
{
const int n = sizeof...(T_Params); //real number of arguments passed.
duk_idx_t num_arguments = duk_get_top(ctx); //Number of arguments from javascript
int x = duk_require_int(ctx, 0); //Get integer -> parameter no 1
const char* c = duk_require_string(ctx, 1); //Get string -> parameter no 2
}
}
template<typename T_Return(typename ... T_Params)>
duk_c_function_t duk_function(std::function<T_Return(T_Params ...) function_item)
{
return duk_c_function_t(detail::duk_function_proxy<function_item>);
}
Where duk_function returns a function of the signature duk_ret_t function(duk_context* ctx) { ... }. Now, i know how to call the function object in duk_function_proxy with the variadic templates and such. But there is one problem for me: The javascript interpreter i am using requires that, for every c-function i want to expose, i need query the parameters from the stack, as shown in duk_function_proxy. However, with that being the case, i dont know how to call the function object - i can only store the queried parameters in some sort of container, and thus i cannot call the function object with the given signature. Is there any way to store my queried parameters in some sort of container, and then unpack and pass it to the function object as parameters? I query the required parameters based on the variadic template list, as seen in the prototype.
In short:
I want to iterate over T_Params, get and store the corresponding variables using duk_require_* (in some sort of container), and then use those values to call the function object, which is passed as a template argument.
this should get you started. I've simulated the DUK interface since it's not installed on my machine but you'll get the idea:
#include <iostream>
#include <string>
#include <functional>
#include <utility>
struct duk_context;
const char* duk_require_string(duk_context*, int i)
{
static constexpr const char * strings[] = {
"i like",
"hairy",
"ducks"
};
return strings[i];
}
int duk_require_int(duk_context*, int i)
{
return i * 6;
}
template<class Type> auto get_arg(duk_context* ctx, int i) -> Type;
template<> auto get_arg<std::string>(duk_context* ctx, int i) -> std::string
{
return duk_require_string(ctx, i);
}
template<> auto get_arg<int>(duk_context* ctx, int i) -> int
{
return duk_require_int(ctx, i);
}
template<class...Args, size_t...Is>
void get_args_impl(duk_context* context, const std::function<void(Args...)>& f, std::index_sequence<Is...>)
{
using tuple_type = std::tuple<Args...>;
f(get_arg<std::tuple_element_t<Is, tuple_type>>(context, Is)...);
}
template<class...Args>
void get_args(duk_context* context, const std::function<void(Args...)>& f)
{
get_args_impl<Args...>(context, f, std::index_sequence_for<Args...>());
}
void foo(std::string a, int b, std::string c)
{
std::cout << a << " " << b << " " << c << std::endl;
}
int main()
{
duk_context* ctx = nullptr;
get_args(ctx, std::function<void(std::string, int, std::string)>(&foo));
return 0;
}
expected output:
i like 6 ducks
Related
I have a structure that in its constructor receives an initialization list std::initializer_list<P...> of type parameter pack. That constructor is filled with lambda functions, and they are saved in a std::vector<P...>.
How can I get the return of those functions when traversing the vector calling each function?
Here is an example of the structure and what I want to do:
#include <iostream>
#include <functional>
#include <initializer_list>
using namespace std;
struct my_type {
my_type(){}
my_type(string _value) : value(_value) {}
string value = "test";
string getValue(){return value;}
};
template<typename A, class...P>
struct struct_name {
struct_name(std::initializer_list<P...> list) : functions(list) {}
std::vector<P...> functions;
string value;
my_type type;
string execute_functions(){
for (size_t i = 0; i < functions.size(); i++)
{
value = functions[i](type); // something like this, this does not work
}
return value;
std::cout << value;
}
};
typedef struct_name<std::function<void(my_type)>, std::function<void(my_type)>> _functions;
int main(int argc, char const *argv[])
{
_functions object = {
[](my_type var)->string{
return var.getValue();
},
[](my_type var)->string{
return var.getValue();
},
};
return 0;
}
Everything works perfect except the way to obtain those values. I don't know how, and no matter how hard I look I can't find answers.
EDIT: I can't paste the complete code, because it depends on many other classes. I tried to recreate that section, the type is a parameter pack because it receives multiple types besides lambdas, but in the example I just put it that way.
If you are trying to process a value through a series of function you can just use std::accumulate:
#include <iostream>
#include <vector>
#include <functional>
#include <numeric>
int main()
{
std::vector<std::function<float(float)>> functions = {
[] (float f) { return f*f; },
[] (float f) { return f + 2; }
};
float result = std::accumulate(functions.begin(), functions.end(), 1.5f,
[] (float v, const auto& lambda) {
return lambda(v);
}
);
std::cout << 1.5f << " -> " << result << std::endl;
return 0;
}
But a vector can only contain one specified type, so what you are trying to do with you parameter pack P... doesn't make much sense, if you want to process multiple values through multiple functions with different signatures you'd better try with something like std::tuple<std::function<T1(T2)>, std::function<T3(T4)>, ...> and pass multiple values to it.
You should be using std::tuple, if you want to store arbitrary callable objects.
You can combine std::index_sequence with a fold expression for calling the functions:
#include <iostream>
#include <string>
#include <tuple>
#include <utility>
using std::string;
struct my_type {
my_type(){}
my_type(string _value) : value(_value) {}
string value = "test";
string getValue(){return value;}
};
template<class...P>
struct struct_name {
struct_name(P... args)
: functions(args...)
{}
std::tuple<P...> functions;
std::string value;
my_type type;
std::string execute_functions() {
return execute_helper(std::make_index_sequence<sizeof...(P)>{});
}
private:
template<size_t ...Is>
std::string execute_helper(std::index_sequence<Is...>)
{
((value += std::get<Is>(functions)(type)), ...);
return value;
}
};
int main()
{
struct_name foo(
[](my_type var)->string {
return var.getValue();
},
[](my_type var)->string {
return var.getValue();
});
std::cout << foo.execute_functions() << '\n';
return 0;
}
I need to create an adapter C++ class, which accepts an integer index, and retrieves some types of data from a C module by the index, and then returns it to the C++ module.
The data retrieving functions in the C module are like:
int getInt(int index);
double getDouble(int index);
const char* getString(int index);
// ...and etc.
I want to implement an array-like interface for the C++ module, so I created the following class:
class Arguments {
public:
template<typename T> T operator[] (int index);
};
template<> int Arguments::operator[] (int index) { return getInt(index); }
template<> double Arguments::operator[] (int index) { return getdouble(index); }
template<> std::string Arguments::operator[] (int index) { return getString(index); }
(Template class doesn't help in this case, but only template member functions)
The adapter class is no biggie, but calling the Arguments::operator[] is a problem!
I found out that I can only call it in this way:
Arguments a;
int i = a.operator[]<int>(0); // OK
double d = a.operator[]<double>(1); // OK
int x = a[0]; // doesn't compile! it doesn't deduce.
But it looks like a joke, doesn't it?
If this is the case, I would rather create normal member functions, like template<T> T get(int index).
So here comes the question: if I create array-operator-overloading function T operator[]() and its specializations, is it possible to call it like accessing an array?
Thank you!
The simple answer is: No, not possible. You cannot overload a function based on its return type. See here for a similar quesiton: overload operator[] on return type
However, there is a trick that lets you deduce a type from the lhs of an assignment:
#include <iostream>
#include <type_traits>
struct container;
struct helper {
container& c;
size_t index;
template <typename T> operator T();
};
struct container {
helper operator[](size_t i){
return {*this,i};
}
template <typename T>
T get_value(size_t i){
if constexpr (std::is_same_v<T,int>) {
return 42;
} else {
return 0.42;
}
}
};
template <typename T>
helper::operator T(){
return c.get_value<T>(index);
}
int main() {
container c;
int x = c[0];
std::cout << x << "\n";
double y = c[1];
std::cout << y ;
}
Output is:
42
0.42
The line int x = c[0]; goes via container::get_value<int> where the int is deduced from the type of x. Similarly double y = c[1]; uses container::get_value<double> because y is double.
The price you pay is lots of boilerplate and using auto like this
auto x = c[1];
will get you a helper, not the desired value which might be a bit unexpected.
I have many defined functions as follows, all return an int
int fn1(int x) {
return x;
}
int fn2(std::string x, int y, std::string z) {
// process string x and z
int x1 = process(x);
int z1 = process(z);
return x1 + y + z1;
}
// ... and many more similar functions
For some reasons, I need to implement a wrapper to call the above functions by function names,
int wrapper(std::string fn_name, some_struct_t data, std::vector<std::string> field_names) {
a_fn_ptr_type fn_ptr = nullptr; // <q1>: is this a right way to do?
// by fn_name, decide which fn to call
if (fn_name == "fn1") {
fn_ptr = &fn1;
}
if (fn_name == "fn2") {
fn_ptr = &fn2;
}
...
// given field_names, get the field from data, pass them to fn_ptr as args
for (auto field_name: field_names) {
std::any value = get_from_data(data, field_name, field_type); // field_type will be updated by this call, so that we know the value type.
// <q2>: but how to pass each value as arg to fn_ptr here?
}
}
The above code demonstrate what I want to achieve, and I have 2 questions (as pointed by <q1> and <q2>).
I'm not sure if the code is the right way to go, hope to get some advice from people, thanks!
Inspired by the comments:
A wrapper that takes some_struct_t data, std::vector<std::string> field_names. Assuming a
template <typename T>
T get_from_data(some_struct_t, std::string);
You have a function type
using func_t = std::function<int(const some_struct_t &, const std::vector<std::string>&)>;
which you can instantiate from functions via
template <typename... Args, size_t... Is>
auto wrap_impl(int(*func)(Args...), std::index_sequence<Is...>)
{
return [func](const some_struct_t & data, const std::vector<std::string>& field_names)
{ return func(get_from_data<Args>(data, field_names.at(Is))...); };
}
template <typename... Args>
func_t wrap(int(*func)(Args...))
{
return wrap_impl(func, std::index_sequence_for<Args...>{});
}
and then you can have a
std::map<std::string, func_t> functions;
In my project i have functions with different number of input parameters with different types. Since these functions are parts of libraries, I cannot change their definitions or bodies.
void methodA(boolean p1, int p2, long p3){
... some unrelevant code here ...
}
void methodB(int p1, int p2, int p3, long p4){
... some unrelevant code here too ...
}
int methodC(long p4){
...
}
In my project i need to have a method, which would receive the address of one of these functions. Additionally it receives well-formed list of parameters (which fits the function in the first parameter). Then this method has to call the passed function with the passed parameters.
Here is what I have now: (i have simplified the code a bit to make my idea clear)
void intercaller(void* some_func_address, ...){
// VARARGS parameters extractor
va_list listPointer;
va_start( listPointer, some_func_address );
int p1 = va_arg( listPointer, int );
int p2 = va_arg( listPointer, int );
int p3 = va_arg( listPointer, int );
long p4 = va_arg( listPointer, long );
// TODO: THIS IS NOT GENERIC CALL , CANN ONLY CALL METHOD B
((void (*)( int , int , int , long )) some_func_address)( p1 , p2 , p3 , p4 );
va_end( listPointer );
}
My problem is the actual function call. The parameter list in the function call should be generic and should be able to include different number of parameters, sadly i dont know how to do that... I have tried passing varargs list like here:
((void (*)( va_list )) some_func_address)( listPointer);
but this messes up the parameters in the called function...
So my question is: is there a way to call a given function with given parameters in a generic manner? Maybe I need some sort of a typedeff or a wrapper function?
If you don't have std::invoke yet, use variadic templates. To treat void functions nicely, use SFINAE.
template<typename R, typename... Args>
auto call(R(*function)(Args...), Args... args) -> typename std::enable_if<!std::is_same<R, void>::value, R>::type {
return function(args...);
}
template<typename... Args>
void call(void (*function)(Args...), Args... args) {
function(args...);
}
Example:
void a() {
std::cout << 'a';
}
void b(int a) {
std::cout << "b:" << a;
}
int c(int a) {
return a;
}
int main() {
call(a);
call(b, 1);
std::cout << "c:" << call(c, 2);
}
Don't forget to #include <type_traits> for std::enable_if and std::is_same.
Try it online!
va_args are still somewhat black magic to me, but I believe the second arg to va_start should be the first arg to the called function. I don't understand what your "clazz" is. I believe you you should call va_start as:
va_start( listpointer, some_func_address );
instead of:
va_start( listPointer, clazz );
Would this help you out?
#include <stdarg.h>
template <typename T>
T extract(va_list& list)
{
return va_arg(list, T);
}
template<typename Result, typename ... Parameters>
Result call(Result(*function)(Parameters...), va_list& list)
{
return function(extract<Parameters>(list)...);
}
void f1(int x, int y)
{
std::cout << x << ' ' << y << std::endl;
}
void f2(double x, double y)
{
std::cout << x << ' ' << y << std::endl;
}
void interceptor(void* f, ...)
{
va_list list;
va_start(list, f);
if(f == &f1)
{
call(f1, list);
}
else if(f == f2)
{
call(f2, list);
}
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor((void*)&f1, 7, 7);
interceptor((void*)&f2, 10.12, 12.10);
return 0;
}
I personally would yet prefer pasing an enum representing the functions to the interceptor function instead of the void* pointer and using switch/case inside.
If you can make the interceptor a template function, it gets even much easier (drop the call template function entirely):
template<typename Result, typename ... Parameters>
void interceptor(Result(*function)(Parameters...), ...)
{
va_list list;
va_start(list, function);
function(extract<Parameters>(list)...);
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor(&f1, 7, 7);
interceptor(&f2, 10.12, 12.10);
return 0;
}
Now coming from your other question, what about this:
(Side note: referenced question tells (in the comments) the void* pointers are coming from some custom map, so there shouldn't be – as far as I can see – any issue with replacing them by other appropriate pointers/classes – which I am going to do...)
#include <stdarg.h>
class FunctionWrapper
{
public:
virtual ~FunctionWrapper() { }
virtual void operator()(va_list&) = 0;
};
template<typename Result, typename ... Parameters>
class FWrapper : public FunctionWrapper
{
Result (*mFunction)(Parameters...);
template <typename T>
T extract(va_list& list)
{
return va_arg(list, T);
}
public:
FWrapper(Result (*function)(Parameters...))
: mFunction(function)
{ }
virtual void operator()(va_list& list)
{
static_cast<void>(mFunction(extract<Parameters>(list)...));
}
};
// facilitates creating the wrappers:
template<typename Result, typename ... Parameters>
FunctionWrapper* createWrapper(Result (*function)(Parameters...))
{
return new FWrapper<Result, Parameters ...>(function);
}
void f1(int x, int y)
{
std::cout << x << ' ' << y << std::endl;
}
void f2(double x, double y)
{
std::cout << x << ' ' << y << std::endl;
}
// e. g.:
FunctionWrapper* gWrappers[] = { createWrapper(&f1), createWrapper(&f2) };
// from your other question: you'd fill the wrappers into the map you mentioned there:
// map[whatever] = createWrapper(&function);
void interceptor(FunctionWrapper* wrapper, ...)
{
va_list list;
va_start(list, wrapper);
(*wrapper)(list);
va_end(list);
}
int main(int argc, char* argv[])
{
interceptor(gWrappers[0], 7, 7);
interceptor(gWrappers[1], 10.12, 12.10);
return 0;
}
This solves the issue via polymorphism: A function wrapper class template class (we need a non-template base class to be able to place all the template instances into an array or a map; this is what your original – but actually illegal – void* pointer served for), resolving the va_list into arguments and calling the original function with...
Can I use C++ template classes to differentiate object types? Or what should I use?
Eg. I have a class Synonym and it can be of type Statement, Procedure, etc for example. I have functions that accepts these synonyms and evaluates them depending on its type. So I was thinking it will be nice if I can do something like:
enum Types { Statement, Procedure, Variable, ... };
template <typename Types>
class Synonym { ... }
void evaluate(Synonym<Statement> s, Synonym<Variable> v) { do something }
^ so that I can do this ... instead of checking the type in function like:
void evaluate(Synonym s, Synonym v) {
assert(s.type == Statement);
assert(v.type == Variable);
// also would like to eliminate things like: (if possible)
switch(s.type) {
case XXX: doSomething ...
case YYY: doAnotherThing ...
}
}
You could create a function template and then specialize on that template
template<typename Type>
void evaluate (Type t) {}
template<>
void evaluate<Statement>( Statement s)
{}
This way, when you pass a Statement it will pick that overload, and you can do different behaviors depending on type.
I think using a variant and visitor pattern would be suited. Have a look at Boost.Variant here: http://www.boost.org/doc/libs/1_51_0/doc/html/variant.html, the last example (also below but expanded) shows a visitor implementation. There are also other variant and visitor implementations. std::any and loki are also options. I personally like loki but that is probably just because I'm a huge fan of Alexandrescu.
#include "boost/variant.hpp"
#include <iostream>
class ToLengthVisitor : public boost::static_visitor<int>
{
public:
int operator()(int i) const
{
return i;
}
int operator()(const std::string & str) const
{
return str.length();
}
int operator()(const char * str) const
{
const char * temp = str;
while(*temp != '\0') temp++;
return temp-str;
}
};
int main()
{
typedef boost::variant< int, std::string, const char * > MyVariant;
MyVariant u(std::string("hello world"));
std::cout << u; // output: hello world
MyVariant cu(boost::get<std::string>(u).c_str());
int result = boost::apply_visitor( ToLengthVisitor(), u );
std::cout << result; // output: 11 (i.e., length of "hello world")
result = boost::apply_visitor( ToLengthVisitor(), cu );
std::cout << result; // output: 11 (i.e., length of "hello world")
}