The Problem:
I've been searching on here for a while looking for a way to loop through variables named somewhat like variable_1, variable_2, ...., variable_n. Basically, I'm asking if there's a way to do that using a loop to achieve variable_i or, more specifically in my case, functionName_i.
What I need: I'm trying to loop an objects' array to call different functions which are sequentially-named and parallel to the objects' array ( i.e: obj[ i ]->callback_i( ) )
What I Know: Obviously, the answer here (if it were just variables) is using an array or vector. However, I need to just concatenate the functions' names sequentially somehow if it's possible.
Possible Workarounds: Everything I think of goes back to creating an array/vector of function pointers. I might get it eventually to work if I'm really out of options, but I just thought I should ask out of curiosity.
Clear Question: Is there a way to loop through sequentially-named functions using a variable int i as part of the functions' names?
Thanks!
No.
C++ does not usually store type or variable name information at runtime; if it does, it's not portable (typeid() does vary across compilers) or it's just not possible. You can't reference a variable name at runtime unless you make a system to do that sort of thing, or you use debugging information, which isn't a standard C++ feature.
This type of reflection is expensive and is more suited towards higher-level languages. C++, as a more lower-level language, strips off the sugar and just tells you "no."
You can make this type of thing in C++ if you make a naming system, but a generalized one would also require variants, a version of the NULL/Maybe idiom, attributes, checks, lots of debugging and you can do it all if you wish, but this is where you might as well switch to another language that already has the answer you're looking for and bind C++ to it.
Alternatively, use a matrix or array of functions. Then, iterate by index.
Related
Right now, I am trying to call a function in C++ through a Json object. The Json object would provide me with the name of the callee function and all the parameters. I will be able to extract the parameters using a for loop, but I am not sure how I can pass them in. For loop only allows me to pass arguments one by one, and I did not find a way to call a function besides passing in all the arguments at once.
I've made a temporary solution of:
if (parameter_count == 1)
func(param_1);
if (parameter_count == 2)
func(param_1, param_2);
...
This solution seems would not work for all cases since it can only work for functions with a limited number of arguments (depending on how many ifs I write). Is there a better way for this? Thanks!
EDIT: Sorry if I was being unclear. I do not know anything about func. I will be reading func from DLL based on its string name. Since I can't really change the function itself, I wouldn't be able to pass in a vector or struct directly.
Or perhaps did I have the wrong understanding? Are we allowed to pass in a single vector in place of a lot of parameters?
Sorry for making a mess through so many edits on this question. Brandon's solution with libffi works. Thanks!
So the problem as I understand it is that you have a void * pointer (which would come from your platform's DLL loading code) which "secretly" is a pointer to a function with a signature which is only known at runtime. You'd like to call this function at runtime with specified arguments.
Unfortunately, this is not possible to do cleanly with standard C++ alone. C++ cannot work with types that are not present in the program at compile-time, and since there is an infinite number of potential function signatures involved here there is no way to compile them all in.
What you'll want to do instead is manually set up the stack frame on your call stack and then jump to it, either via inline assembly or via some library or compiler extension that accomplishes this for your platform.
Here is a simple example of doing this via inline assembly. (To do this in general you will need to learn your platform's calling convention in detail, and needless to say this will constrain your program to the platform(s) you've implemented this for.)
I haven't actually tried it, but gcc has a compiler extension __builtin_apply that is apparently just meant to forward the arguments from one method wholesale to another but which could perhaps be used to accomplish something like this if you learned the (apparently opaque) description of the method.
[Update: Apparently I missed this in the comments, but Brandon mentioned libffi, a library which implements a bunch of platforms' calling conventions. This sounds like it might be the best option if you want to take this sort of approach.]
A final option would be to constrain the allowed signatures of your functions to a specified list, e.g. something like
switch(mySignature)
{
case VOID_VOID:
dynamic_cast<std::function<void(void)> *>(myPtr)();
break;
case VOID_INT:
dynamic_cast<std::function<void(int)> *>(myPtr)(my_int_arg_1);
break;
// ...
}
(Syntax of the above may not be 100% correct; I haven't tested it yet.) Whether this approach is sensible for your purposes depends on what you're doing.
In C++ it is possible to declare that a function is const, which means, as far as I understand, that the compiler ensures the function does not modify the object. Is there something analogous in C++ where I can require that a function is pure? If not in C++, is there a language where one can make this requirement?
If this is not possible, why is it possible to require functions to be const but not require them to be pure? What makes these requirements different?
For clarity, by pure I want there to be no side effects and no use of variables other than those passed into the function. As a result there should be no file reading or system calls etc.
Here is a clearer definition of side effects:
No modification to files on the computer that the program is run on and no modification to variables with scope outside the function. No information is used to compute the function other than variables passed into it. Running the function should return the same thing every time it is run.
NOTE: I did some more research and encountered pure script
(Thanks for jarod42's comment)
Based on a quick read of the wikipedia article I am under the impression you can require functions be pure in pure script, however I am not completely sure.
Short answer: No. There is no equivalent keyword called pure that constrains a function like const does.
However, if you have a specific global variable you'd like to remain untouched, you do have the option of static type myVar. This will require that only functions in that file will be able to use it, and nothing outside of that file. That means any function outside that file will be constrained to leave it alone.
As to "side effects", I will break each of them down so you know what options you have:
No modification to files on the computer that the program is run on.
You can't constrain a function to do this that I'm aware. C++ just doesn't offer a way to constrain a function like this. You can, however, design a function to not modify any files, if you like.
No modification to variables with scope outside the function.
Globals are the only variables you can modify outside a function's scope that I'm aware of, besides anything passed by pointer or reference as a parameter. Globals have the option of being constant or static, which will keep you from modifying them, but, beyond that, there's really nothing you can do that I'm aware.
No information is used to compute the function other than variables passed into it.
Again, you can't constrain it to do so that I'm aware. However, you can design the function to work like this if you want.
Running the function should return the same thing every time it is run.
I'm not sure I understand why you want to constrain a function like this, but no. Not that I'm aware. Again, you can design it like this if you like, though.
As to why C++ doesn't offer an option like this? I'm guessing reusability. It appears that you have a specific list of things you don't want your function to do. However, the likelihood that a lot of other C++ users as a whole will need this particular set of constraints often is very small. Maybe they need one or two at a time, but not all at once. It doesn't seem like it would be worth the trouble to add it.
The same, however, cannot be said about const. const is used all the time, especially in parameter lists. This is to keep data from getting modified if it's passed by reference, or something. Thus, the compiler needs to know what functions modify the object. It uses const in the function declaration to keep track of this. Otherwise, it would have no way of knowing. However, with using const, it's quite simple. It can just constrain the object to only use functions that guarantee that it remains constant, or uses the const keyword in the declaration if the function.
Thus, const get's a lot of reuse.
Currently, C++ does not have a mechanism to ensure that a function has "no side effects and no use of variables other than those passed into the function." You can only force yourself to write pure functions, as mentioned by Jack Bashford. The compiler can't check this for you.
There is a proposal (N3744 Proposing [[pure]]). Here you can see that GCC and Clang already support __attribute__((pure)). Maybe it will be standardized in some form in the future revisions of C++.
In C++ it is possible to declare that a function is const, which means, as far as I understand, that the compiler ensures the function does not modify the object.
Not quite. The compiler will allow the object to be modified by (potentially ill-advised) use of const_cast. So the compiler only ensures that the function does not accidentally modify the object.
What makes these requirements [constant and pure] different?
They are different because one affects correct functionality while the other does not.
Suppose C is a container and you are iterating over its contents. At some point within the loop, perhaps you need to call a function that takes C as a parameter. If that function were to clear() the container, your loop will likely crash. Sure, you could build a loop that can handle that, but the point is that there are times when a caller needs assurance that the rug will not be pulled out from under it. Hence the ability to mark things const. If you pass C as a constant reference to a function, that function is promising to not modify C. This promise provides the needed assurance (even though, as I mentioned above, the promise can be broken).
I am not aware of a case where use of a non-pure function could similarly cause a program to crash. If there is no use for something, why complicate the language with it? If you can come up with a good use-case, maybe it is something to consider for a future revision of the language.
(Knowing that a function is pure could help a compiler optimize code. As far as I know, it's been left up to each compiler to define how to flag that, as it does not affect functionality.)
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.
I'm experimenting with variable arguments in C++, using va_args. The idea is useful, and is indeed something I've used a lot in C# via the params functionality. One thing that frustrates me is the following excerpt regarding va_args, above:
Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list).
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself. I would like to perform something like the following:
void fcn(int arg1 ...)
{
va_list argList;
va_start(argList, arg1);
int numRemainingParams = //function that returns number of remaining parameters
for (int i=0; i<numRemainingParams; ++i)
{
//do stuff with params
}
va_end(argList);
}
To reiterate, the documentation above suggests that va_arg doesn't determine whether the retrieved arg is the last in the list. But I feel this information must be accessible in some manner.
Is there a standard way of achieving this?
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself.
Nonetheless, it is true. C/C++ do not put markers on the end of the argument list, so the called function really does not know how many arguments it is receiving. If you need to mark the end of the arguments, you must do so yourself by putting some kind of marker at the end of the list.
The called function also has no idea of the types or sizes of the arguments provided. That's why printf and friends force you to specify the precise datatype of the value to interpolate into the format string, and also why you can crash a program by calling printf with a bad format string.
Note that parameter passing is specified by the ABI for a particular platform, not by the C++/C standards. However, the ABI must allow the C++/C standards to be implementable. For example, an ABI might want to pass parameters in registers for efficiency, but it might not be possible to implement va_args easily in that case. So it's possible that arguments are also shadowed on the stack. In almost no case is the stack marked to show the end of the argument list, though, since the C++/C standards don't require this information to be made available, and it would therefore be unnecessary overhead.
The way variable arguments work in C and C++ is relatively simple: the arguments are just pushed on the stack and it is the callee's responsibility to somewhat figure out what arguments there are. There is nothing in the standard which provides a way to determine the number of arguments. As a result, the number of arguments are determined by some context information, e.g., the number of elements referenced in a format string.
Individual compilers may know how many elements there are but there is no standard interface to obtain this value.
What you could do instead, however, is to use variadic templates: you can determine very detailed information on the arguments being passed to the function. The interface looks different and it may be necessary to channel the arguments into some sort of data structure but on the upside it would also work with types you cannot pass using variable arguments.
No, there isn't. That's why variable arguments are not safe. They're a part of C, which lacks the expressiveness to achieve type safety for "convenient" variadic functions. You have to live with the fact that C contains constructions whose very correctness depends on values and not just on types. That's why it is an "unsafe language".
Don't use variable arguments in C++. It is a much stronger language that allows you to write equally convenient code that is safe.
No, there's no such way. If you have such a need, it's probably best to pack those function parameters in a std::vector or a similar collection which can be iterated.
The variable argument list is a very old concept inherited from the C history of C++. It dates back to the time where C programmers usually had the generated assembler code in mind.
At that time the compiler did not check at all if the data you passed to a function when calling it matched the data types the function expected to receive. It was the programmer's responsibility to do that right. If, for example, the caller called the function with a char and the function expected an int the program crashed, although the compiler didn't complain.
Today's type checking prevents these errors, but with a variable argument list you go back to those old concepts including all risks. So, don't use it if you can avoid it somehow.
The fact that this concept is several decades old is probably the reason that it feels wrong compared to modern concepts of safe code.
One could break the question into two: how to read and to write templated code.
It is very easy to say, "it you want an array of doubles, write std::vector<double>", but it won't teach them how the templates work.
I'd probably try to demonstrate the power of templates, by demonstrating the annoyance of not using them.
A good demonstration would be to write something simple like a stack of doubles (hand-written, not STL), with methods push, pop, and foldTopTwo, which pops off and adds together the top two values in the stack, and pushes the new value back on.
Then tell them to do the same for ints (or whatever, just some different numeric type).
Then show them how, by writing this stack as a template, you can significantly reduce the number of lines of code, and all of that horrible duplication.
There is a saying: "If you can't explain it, you don't understand it."
You can break it down further: How to write code that uses templated code, and how to write code that provides a templated service to others.
The basic explanation is that templates generated code based on a template. That is the source of the term "meta programming". It is programming how programming should be done.
The essential complexity of a vector is not that it is a vector of doubles (or type T), but that it is a vector. The basic structure is the same and templates separate that which is consistent from that which is not.
Further explanation depends on how much of that makes sense to you!
IMHO it is best to explain them as (very) fancy macros. They just work at higher level than C-style text substitution macros.
I found it very instructive to look at duck-typed languages. It doesn't matter, there, what type of argument you give a function, as long as they offer the right interface.
Templates allows to do the same thing: you can take any type, as long as the right interface is present. The additional benefit over duck-typing is, that the interface is checked at compile-time.
Present them as advanced macros. It's a programming language on its own that is executed during compliation.
I would get them to implement something themselves, then experiment with different variations until they understand it. Learning by doing is almost always the better option with programming.
For example, get them to make a template which compares two values and returns the higher one. Then have them see has passing ints or doubles or whatever still allows it to work. Then get them to tweak the the code / copy it and have it return the minimum value. Again, experiment with variations - will the template allow them to pass an int and a double, or will it complain?
From there, you can have them pass in arrays of whatever type (int, double etc), and have it sort the array from highest to lowest, again encouraging experimentation. From there, start to move into templated class definitions, using the same kind of ideas but on a larger scale. This is pretty much how I learnt about templates, ending up with complex array manipulation classes for generic types.
When I was teaching myself C++ I used this site a lot. It explains templates in depth and very well. I would recommend having them read that and try implementing something simple.
For a shorter explanation: Templates are frameworks for complicated constructs that act on data without having to know what that data is. Give them some examples of a simple template (like a linked-list) and walk through how the template is used to generate the final class.
You can tell that a template is a half-written source with parameters to be filled while instatiating the template.