It's easy to do something like that in Python, but implementing it in C++ seems to be more challenging.
I actually have some solution to this, but I'd like to see if you can see any better solution.
Here's what I want to do.
I have a list of values of different types (string, integer, can be also instance of some class etc.). Now here's the first problem - in C++ (unlike in Python) all values in vector/array have to be of the same type.
The solution I can see is that I can use std::any like this: vector<std::any> list.
I also have an array/vector of functions (or pointers to functions) with different parameter types and returned values - one function can accept string and integer and return a char and other can accept a char and return an int. Here's another problem: in C++ you can have an array/vector of functions only if they have the same parameters and returned values (as far as I know) because in your declaration of the vector you need to define the parameter types and the returned value.
The other problem is that I need to retrieve the information about the parameters and the returned value for each function. In other words, having those functions, I need to know that this function accepts 2 strings and 1 integer and returns a char for example. In Python I can use inspect.signature function to retrieve information about type annotations of a function. In C++, I don't know if there is a way to do this.
The solution I can see here is to use std::any again (although I will use another solution, I will explain why later).
The solution I can see to this problem is that I won't retrieve that information but instead the user of the class which accepts this vector of functions will simply have to specify what are the parameter types and returned value for each function. In other words, the solution I can see is that I won't be retrieving the information about parameter types programmatically.
The other problem I have is that later I need to call one of those functions with some parameters. In Python I do this like this:
arguments = [1, 'str', some_object] // here I prepare a list of arguments (they are of different types)
func(**arguments)
In C++ I can do unpacking as well, but not if the parameters are of different types.
The solution I can see here is as follows. Those functions in the vector will all accepts only argument which is vector<std::any> args which will simply contain all of the arguments. Later when I want to call the function, I will simply construct a vector with std::any values and pass it as an argument. This would also solve the previous problem of not being able to store vector of functions with different parameters.
Can you see better solutions?
You might wonder what I need all of this is for. I do some program synthesis stuff and I need to programmatically construct programs from existing functions. I'm writing a library and I want the user of my library to be able to specify those base functions out of which I construct programs. In order to do what I want, I need to know what are the parameters and returned values of those functions and I need to call them later.
I believe what you are looking for is std::apply. You can use std::tuple instead of std::vector to store a list of values of different types -- as long as the types are known at compile-time. Then std::apply(f, t) in C++ is basically the same as f(*t) in Python.
I have a list of values of different types (string, integer, can be also instance of some class etc.).
A type which is a union of subtypes is called a sum type or tagged union. C++ has the template std::variant for that.
Now here's the first problem - in C++ (unlike in Python) all values in vector/array have to be of the same type.
Of course, so use cleverly C++ containers. You might want some std::map or std::vector of your particular instance of std::variant.
I also have an array/vector of functions
You probably want some std::vector of std::function-s and code with C++ lambda expressions
You should read a good C++ programming book
I'm writing a library and I want the user of my library to be able to specify those base functions out of which I construct programs.
You could get inspiration from SWIG and consider generating some C++ code in your library. So write (in Python or C++) your C++ metaprogram (generating some C++ code, like ANTLR does) which generates the user code, and your user would adapt his build automation tool for such a need (like users of GNU bison do).
You might also consider embedding Guile (or Lua) in your application.
PS. You might be interested by other programming languages like Ocaml, Go, Scheme (with Guile, and read SICP), Common Lisp (with SBCL), or Rust.
Related
Suppose I have a variadic function like this:
template <typename... A>
void func(A... args)
{
//Do stuff
}
And I have also a vector like this:
enum Type{
DOUBLE,
STRING
};
std::vector<std::pair<std::string, Type>> varg;
So I want to iterate over the elements of the map and call the templated function with the specified types, like: varg = {{"a", Type::STRING}, {"1.2", Type::DOUBLE}};
should call func("a", 1.2)
Any hints on how to do that?
At the lowest level (C-like), the application binary interface follows some calling conventions, notably how arguments are transmitted to a function, and it usually depends on the type of the argument (often, pointers go in some processor registers and floating point numbers go in some other kind of registers).
If you want to call a function of unknown signature (i.e. you know its signature and the actual arguments and their number only at runtime, not at compile time) you need some ABI specific tricks, and probably some machine specific code. You might consider using the libffi which provides
a portable, high level programming interface to various calling conventions
BTW, you could consider packing or boxing your values in some "universal" container à la boost::any or QVariant or your own tagged unions, or perhaps boost::variant
Perhaps you might want to embed some interpreter in your application, e.g. GNU guile or Lua.
Noticve that for C or C++, functions and function pointers have some compile-time known signature which matters a lot. Calling something with the wrong signature (that is a function whose signature is not the one the compiler expects) is undefined behavior.
You are mixing up compile-time and runtime features here. (Hint: It won't work)
As a thought-experiment:
Suppose you have a std::vector<> of some kind, that is filled with some data, say with N entries. Note that this N is a priori only known at runtime!
Now you want to unpack these N data segments into a variadic template, something that has to be done compile-time! Templates are compile-time features!
This cannot work. You can in principle do something similar if you use compile-time containers (see boost::mpl). But these require, that you know (or can calculate) everything at compile-time.
Also you may want to look at boost::fusion which sort of tries to bridge this gap. Though you should always note that it cannot! Templates are still compile-time only.
Usually in my code I need to use specific functions for various variables i.e.
object->SetStatus("var1",1); object->SetAddress("var1",&var1);
object->SetStatus("var2",1); object->SetAddress("var2",&var2);
object->SetStatus("var3",1); object->SetAddress("var3",&var3);
...
My idea is to use a function that will do this automatically by calling it, i.e.
object->function(var1,var2,var3,...);
To achieve that I have to solve 3 issues
I need to read the number of arguments when calling function()
I need to parse somehow the argument names inside the code
Since the variables are not of the same type, I need to find a way to make function() type "transparent"
Since I am newbie in c++ coding, I tried to search fo something similar, but I couldn't find anything.
Any help, advice or remark is more than welcome!
There are multiple ways to do so. One way is make a Base class and all your variable type will inherit from this base class. Then pass a map<string,Base> as an argument to you function. name of variable will be key and value will be actual variables. Iterate through the map and set and assign values to methods.
You could consider some variadic template, if coding in C++11 or C++14. There is considerable literature about that subject (e.g. this tutorial), which is a bit tricky (so explaining it here is not reasonable). Read also about parameter pack
You could also use C style varargs using <cstdarg>
Perhaps std::initializer_list could be useful too.
Ive spent the day reading notes and watching a video on boost::fusion and I really don't get some aspects to it.
Take for example, the boost::fusion::has_key<S> function. What is the purpose of having this in boost::fusion? Is the idea that we just try and move as much programming as possible to happen at compile-time? So pretty much any boost::fusion function is the same as the run-time version, except it now evaluates at compile time? (and we assume doing more at compile-time is good?).
Related to boost::fusion, i'm also a bit confused why metafunctions always return types. Why is this?
Another way to look at boost::fusion is to think of it as "poor man introspection" library. The original motivation for boost::fusion comes from the direction of boost::spirit parser/generator framework, in particular the need to support what is called "parser attributes".
Imagine, you've got a CSV string to parse:
aaaa, 1.1
The type, this string parses into, can be described as "tuple of string and double". We can define such tuples in "plain" C++, either with old school structs (struct { string a; double b; } or newer tuple<string, double>). The only thing we miss is some sort of adapter, which will allow to pass tuples (and some other types) of arbitrary composition to a unified parser interface and expect it to make sense of it without passing any out of band information (such as string parsing templates used by scanf).
That's where boost::fusion comes into play. The most straightforward way to construct a "fusion sequence" is to adapt a normal struct:
struct a {
string s;
double d;
};
BOOST_FUSION_ADAPT_STRUCT(a, (string, s)(double, d))
The "ADAPT_STRUCT" macro adds the necessary information for parser framework (in this example) to be able to "iterate" over members of struct a to the tune of the following questions:
I just parsed a string. Can I assign it to first member of struct a?
I just parsed a double. Can I assign it to second member of struct a?
Are there any other members in struct a or should I stop parsing?
Obviously, this basic example can be further extended (and boost::fusion supplies the capability) to address much more complex cases:
Variants - let's say parser can encounter either sting or double and wants to assign it to the right member of struct a. BOOST_FUSION_ADAPT_ASSOC_STRUCT comes to the rescue (now our parser can ask questions like "which member of struct a is of type double?").
Transformations - our parser can be designed to accept certain types as parameters but the rest of the programs had changed quite a bit. Yet, fusion metafunctions can be conveniently used to adapt new types to old realities (or vice versa).
The rest of boost::fusion functionality naturally follows from the above basics. fusion really shines when there's a need for conversion (in either direction) of "loose IO data" to strongly typed/structured data C++ programs operate upon (if efficiency is of concern). It is the enabling factor behind spirit::qi and spirit::karma being such an efficient (probably the fastest) I/O frameworks .
Fusion is there as a bridge between compile-time and run-time containers and algorithms. You may or may not want to move some of your processing to compile-time, but if you do want to then Fusion might help. I don't think it has a specific manifesto to move as much as possible to compile-time, although I may be wrong.
Meta-functions return types because template meta-programming wasn't invented on purpose. It was discovered more-or-less by accident that C++ templates can be used as a compile-time programming language. A meta-function is a mapping from template arguments to instantiations of a template. As of C++03 there were are two kinds of template (class- and function-), therefore a meta-function has to "return" either a class or a function. Classes are more useful than functions, since you can put values etc. in their static data members.
C++11 adds another kind of template (for typedefs), but that is kind of irrelevant to meta-programming. More importantly for compile-time programming, C++11 adds constexpr functions. They're properly designed for the purpose and they return values just like normal functions. Of course, their input is not a type, so they can't be mappings from types to something else in the way that templates can. So in that sense they lack the "meta-" part of meta-programming. They're "just" compile-time evaluation of normal C++ functions, not meta-functions.
so i use BOOST.EXTENTION to load modules. I have a special file that describes each module. I read variables from that file.
so such example:
shared_library m("my_module_name");
// Call a function that returns an int and takes a float parameter.
int result = m.get<int, float>("function_name")(5.0f);
m.close();
for me would turn into:
shared_library m("my_module_name");
// Call a function that returns an int and takes a float parameter.
int result = m.get<myMap["TYPE_1_IN_STRING_FORM"], myMap["TYPE_2_IN_STRING_FORM"]>("function_name")(5.0f);
m.close();
How to create such map that would map standard and costume types?
Update:
may be with variant:
shared_library m("my_module_name");
int result = m.get<boost::variant< int, float, ... other types we want to support >, boost::variant< int, float, ... other types we want to support > >("function_name")(5.0f);
m.close();
can halp? so we would not care as long as all types we want are declared in it?
For that, you would need a heterogeneous map - that is, its elements can be of different types. Furthermore you would need the ability to return types from functions, not just variables.
Now, a heterogeneous map would be possible with Boost.Variant or a simple union, but that binds it to compile time: we need to know every type that is possible to create that variant/union.
Of course a Boost.Any would be possible to store everything and its dog, but the problem strikes again: you need to extract the real type out of that Boost.Any again. The problem repeats itself. And if you know the real type, you can aswell just make a variant/union and save yourself the any_cast trouble.
Now, for another troublesome thing:
m.get<myMap["TYPE_1_IN_STRING_FORM"], myMap["TYPE_2_IN_STRING_FORM"]>
To make the above line work, you'd need two features that C++ doesn't have: the ability to return types and runtime templates. Lets ignore the first point for a moment.
Templates are compile-time, and the get function is such a template. Now, to use that template, your myMap would need to be able to return types at compile-time, while getting populated at runtime. See the contradiction? That's why runtime templates would be needed.
Sadly, exactly those three things are not possible (or extremely hard and very very limited) in C++ at runtime: heterogeneous data types (without constant size), returning types and templates.
Everything that involves types needs to be done at compile-time. This blogpost by #Gman somewhat correlates with that problem. It's definitly worth a read if you want to know what C++ just can't do.
So, to conclude: You'll need to rethink and refactor your problem and solution. :|
I need an array to hold member-function-pointers of different classes. How can I define the array?
The code should look like this:
arr[0] = &CMyClass::FuncX;
arr[1] = &CYourClass::FuncY;
arr[2] = &CHerClass::FuncZ;
I tried void*, but it doesn't work.
You can't; they are all different types and arrays are homogeneous.
Regardless what the arguments are or what the return value is, there is an implicit this which is unique to the class type. The type of a class member pointer is:
return_value (class_type::*)(parameters);
As you can see, because they belong to different classes they will always be a different type. Even if it were the same class, the return_value and parameters would have to be consistent to create an array, otherwise you'd still have different types.
What's the bigger picture? Boost.Bind with Boost.Function comes to mind. Also, virtual functions may solve your problem.
As others have pointed out, you can't store pointers to different kinds of functions directly. You might want to look at the Command template, e.g., from Modern C++ Design, which at least lets you put different invokable "things" (pointers or smart pointers to functions, functors, member functions) into a single thing.
On its own, that probably won't be sufficient -- you'll (apparently) end up with the template instantiated over different types, which produces different types. Those types will all use the same syntax, but won't all go into an array (which demands a single type).
Depending on your constraints, (compile-time vs. run-time indexing, in particular) you may be able to use a Boost::tuple to store a collection of command objects. You can treat that a bit like an array, using numeric indexing to get to an individual item. Unlike a normal array, however:
the syntax is a bit ugly, and
The indexing has to be done at compile-time (using compile-time constants).
Without know the parameters or return types of the function its hard to define them for you look at this page to get the gist of it or post the declaration of the functions.
Others have noted why you can't do this. But even if you could, what would you be able to do with it. In order to call a member function pointer, you need to an object of the appropriate type to call it on. So you would need to know the type of each of the member function pointers. You need to take a step back and figure out what it is that you are trying to accomplish.