What type can hold member-function-pointers of difference classes in C++? - c++

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.

Related

Passing arguments by template -- for efficiency?

There are two standard methods of passing arguments -- by value, and constant reference. Each has its trade-offs, with value being preferable in most cases that the data is very small. However, I just recently looked into templates more, and the way I understand it, they act more like a macro. Could you use templates to favor efficiency (disregarding bad code cleanliness for now)? For example, if I passed a std::vector through a template, would it allow access to the current scope to the function called?
I think you are misunderstanding what templates are.
Template arguments are not another way of passing runtime arguments to a function. Templates are a way essentially of doing code generation if you want to use the exact same code multiple times but with different types and/or constants when you know all the types and constant values at compile time.
So to answer your question
For example, if I passed a std::vector through a template, would it
allow access to the current scope to the function called?
you can't pass an std::vector value to a template function beyond normal argument passing which may be parametrized on the type. As for allowing access to a vector in the current scope, you don't need templates for that anyway: pass a reference to the vector.

C++ Array of different functions

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.

Error with std::bind and templated member functions

I am currently writing a gameboy emulator for practicing C++. I have gotten to the part where I implement CPU instructions and decided a vector of std::function was a good choice.
Please note: u8 is an alias for uint8_t.
In my code, there is a vector of std::function<u8()> with three types of members:
A lambda expression that returns u8.
Pointer to a member function.
Pointer to a templated member function.
I tried to use an initalizer list at first, but it didn't work. I later found out that is because I needed a call to std::bind(/*function ptr*/, this); on the pointers, but when calling this on the templated function pointers, I get the following error: no matching function for call to 'bind'. I would like to have an initalizer list, as right now it is a function with successive calls to emplace_back.
Here is the erroring line:
instruction_set.emplace_back(bind(&CPU::OPLoadDualRegister8<B, B>, this)); // 0x40 LD B, B
One interesting thing is that when B is replaced with a literal (e.g. 0x00) it works perfectly. B is a u8 and that is what the template accepts.
So:
Is there any way I can do this less convoluted? (e.g. init lists, std::function with member function ptrs, etc.)
If this is the best way, what do I do about the templated ptrs?
Would it better if I took the template params as args and used std::bind to resolve them (all params are either u8 or u8&.
Any optimization suggestions?
Thanks, Zach.
Okay, there is a lot going on here between your question and the comments. Here are some things I notice right off the bat:
If you are going to index into a vector to decode op codes, you probably shouldn't just emplace_back into the vector in order. Instead grow the vector to its final size, filling it with null values and use the subscript operator to put the functions in. instruction_set[0x40] = ...
Using a switch statement and just calling the functions directly is likely a way better choice. Obviously, don't know the ins and outs of your project, so this may not be possible.
When you say B is u8 do you mean B is variable of type u8? Plain 'ol variables can't be used to instantiate templates. B would have to be a macro, template parameter on the calling function, constexpr variable, or static const (basically known at compile time).
std::bind is never any fun for anyone to use, so you are not alone. I don't think it is the root cause of your issue here, but you should probably prefer binding things using capturing lambdas.
Funnily enough C++'s new hearthrob Matt Godbolt (author of Compiler Explorer) gave a talk on emulating a 6502 in JavaScript last year. It's not exactly an authoritative reference on the subject, but it may be worth a watch if you are interested in emulating old microprocessors.

Call variadic function in C++ with a vector of arguments

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.

Boost how to create a map for types selection?

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. :|