Function name generation and calling in C++ - c++

I have 10 functions with generic names which return references like:
int& function0();
int& function1();
...int& functionN();
As you can see only one letter changes in the function name. Each function does a different job. My use case is given some length, say L, I have to call functions from 0 to L. So I want to somehow generate these function names and call them instead of hardcoding all the function calls based on L. So if in a loop where index i is from 0 to L, for each i I want to call functioni().
One approach that I tried was to store these functions into an array of function pointers but that does not work as these functions return references and array of references is not possible. I also tried to use macro concatenation to generate function names but that is also not possible because macro cannot substitute the value of some variable at preprocessing (MACRO(function,i) does not substitute value of i, concatenates to functioni).
How can I do such thing in C++?

That's not possible in C++, but in your case an array of function pointers seems like a good solution:
typedef int& (* functionPtr)();
functionPtr functions[N];
// or without typedef: int& (* functions[N])();
functions[0] = foo; // assign a function named foo to index 0
int& i = functions[0](); // call function at index 0

You could store an array of function pointers, as answered by Zenith.
In C++11, you could have an array of function closures, e.g. use std::function and lambda expressions. You could have some std::map<std:string,std::function<int&(void)>> associating names to closures.
You could wrap the calls in some function like
int& dofunction(int n) {
switch 0: return function0();
switch 1: return function1();
/// etc...
};
and you could write some small script (e.g. in awk, python, shell, etc....) to generate the C++ code of the above dofunction.
At last, on some operating systems (e.g. Linux and most POSIX), you could retrieve a function pointer at runtime by its name using dlopen(3) (with a NULL filename) then dlsym. You would then declare extern "C" int& function0(); (to avoid name mangling -otherwise you need to pass the mangled name to dlsym) and you need to link the program with -rdynamic -ldl; see C++ dlopen mini howto.

Related

Explaining C++ (C Binding Library) Function

I'm trying to understand a Function/Method in a Library in order to port it to Java however some parameters don't make any sense to me and reading the source code the library is based on is not helping.
Function (Note the API has few comments (We can also ignore the calc handle since it's got a supplier method))
Ssr calc_ssr(CalcHandle *calc, NoteInfo *rows, size_t num_rows, float music_rate, float score_goal) {
std::vector<NoteInfo> note_info(rows, rows + num_rows);
auto skillsets = MinaSDCalc(
note_info,
music_rate,
score_goal,
reinterpret_cast<Calc*>(calc)
);
return skillset_vector_to_ssr(skillsets);
}
NoteInfo Struct
struct NoteInfo
{
unsigned int notes;
float rowTime;
};
MinaSDCalc
// Function to generate SSR rating
auto
MinaSDCalc(const std::vector<NoteInfo>& NoteInfo,
const float musicrate,
const float goal,
Calc* calc) -> std::vector<float>
{
if (NoteInfo.size() <= 1) {
return dimples_the_all_zero_output;
}
calc->ssr = true;
calc->debugmode = false;
return calc->CalcMain(NoteInfo, musicrate, min(goal, ssr_goal_cap));
}
Calc expected input file data (Only care about the #Notes: ...)
Pastebin
Question
What is NoteInfo in calc_ssr, I don't know any C or C++ so the *rows to me just seems like a pointer to a Noteinfo instance, however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me (pairing this with the fact that NoteInfo needs another parameter rowTime which I think is time of Note occurrence in the file which means that value must not be constant otherwise the produced result would be inaccurate)
Github Project: https://github.com/kangalioo/minacalc-standalone (The code alone may not explain enough but it's worth a try; best to look at API.h and discern what's used from there. Though I do warn you a lot of the Code is esoteric)
Sorry if this doesn't make much sense but I've been looking into this since June/July and this API is the closest abstraction from the bare C++ code I could find.
NoteInfo * rows here is pass by pointer. So, rows actually is a pointer to an instance of type NoteInfo. This is one of the ways to pass arrays in c++ to a function. Since arrays are contiguous in memory so we can just increment the pointer by one and get the next element of the array.
for example look at these three ways to do exactly one thing, parameter to pass an array to a function :-
1. void myFunction(int *param) {}
2. void myFunction(int param[10]) {}
3. void myFunction(int param[]) {}
Look into this link for more understanding : https://www.tutorialspoint.com/cplusplus/cpp_passing_arrays_to_functions.htm
Also search for pass by pointer and pass by reference to look into different ways of passing arguments in c++.
2.however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me: as to this question of yours, you can now see MinaSDCalc is actually getting an array and not a single instance as passing the pointer is also one of the ways of passing an array in c++.

How exactly do you pass arrays through the parameters of a function?

I have a project for my class that basically reads 3 students info (each student has 3 courses, and 5 tests, along with info like their name, ssn, phone number, etc.) from an input file, stores the input in arrays, then outputs the information into an output file. The project must be split into 6 functions, not including the main function.
I can successfully read and store the information, but when i go to the "validateData" function, my array is not being passed through to the function, so it will not be able to validate it. This error is also happening throughout the other functions as well. I believe it is probably an error with the prototypes of the functions, as that is what i am mostly confused about it.
i have tried changing the prototype parameters to (string[],int[],double[]) because i have 3 different arrays, one for the strings, one for the ints, and one for the doubles. But this has not worked. I also tried the same thing except without these "[]", still was not working, i believe the error said that the compiler was unable to change a double* into a double, or vice versa.
//Declaring global constants
const int STUDENTS = 3;
const int NONNUMERIC_INFO = 9;
const int NUMERIC_INFO = 2;
const int COURSES = 3;
const int TESTS_and_CNG = 6;
//Above main function, Function prototype
void validateData(string [], int [], double []);
//Inside main function, Function call
validateData();
//Declaring Arrays (inside of a different function called inputData)
string nonNumeric1[STUDENTS][NONNUMERIC_INFO];
int numeric1[STUDENTS][NUMERIC_INFO];
double numeric2[STUDENTS][COURSES][TESTS_and_CNG];
//Under main function, Function definition
void validateData(string, int, double)
{
//A bunch of if statements that i will soon turn into for loops, but will save you guys the trouble of reading them all, as its not important to the question.
}
I am expecting the arrays to be passed through into the function, however it is not doing so and giving me an error saying "error: too few arguments to function 'void validateData(std::__cxx11::string*, int*, double*)'" I am unaware of what the error message is trying to say.
Good job with the prototype function but your function title lines don't match.
Your Prototype:
//Above main function, Function prototype
void validateData(string [], int [], double []);
Your Function:
void validateData(string, int, double)
Secondly, although your prototype may no need variable names, your function title line certainly does.
void validateData(string, int, double) your function here only has variable types. I'd check out a tutorial like declaring functions if you aren't fully familiar with declaring functions.
Finally, once you've matched up your prototype function title line and your actual function title line and gave your actual function parameters variable names, you'll need to fix your function call.
You call your function like so: validateData(); This again, doesn't match your function title line. Your function title line says that validateData takes a string array, int and a double. Your function call passes nothing (). If you want your array, int and double to appear in the function you need to pass them in the function call. validateData(some_array, some_int, some_double).
Don't forget to replace some_array, some_int ... etc with actual variables with their respective types.
Edit:
If you're looking to call the validateData method inside inputData you'd have to do something like:
void inputeData(....) {
validateData(some_array, some_int, some_double);
}

Unable to understand function-pointers in c++

I am reading The C++ Programming Language by Bjarne Stroustrup. It states an example to explain function-pointers:
int cmp1(const void∗ p, const void∗ q) // Compare name strings
{
return strcmp(static_cast<const User∗>(p)−>name,static_cast<const User∗>(q)−>name);
}
Then it uses this cmp1 in ssort, something like this:
int main()
{
cout << "Heads in alphabetical order:\n";
ssort(heads,6,sizeof(User),cmp1);
print_id(heads);
//Rest of function body
}
My question is: is &cmp1 being passed as an argument in ssort() because we can't pass a function as an argument, we can only pass a function-pointer?
My question is: is &cmp1 being passed as an argument in ssort() because we can't pass a function as an argument, we can only pass a function-pointer?
Your code does not use &cmp1. Hence, your question does not match your code.
Still, a function can be passed without using the addressof operator (&).
ssort(heads, 6, sizeof(User), &cmp1);
is the same as
ssort(heads, 6, sizeof(User), cmp1);
Functions decay to function pointers in this context.
A functions name indeed represent the starting address of the executable code for the function. So it's more like the arrays where its name can be used as pointer to the array itself. Also go through
https://www.geeksforgeeks.org/function-pointer-in-c/

D language function call with argument

I am learning D and have mostly experience in C#. Specifically I am trying to use the Derelict3 Binding to SDL2. I have been able to get some basic functionality working just fine but I have become stumped on how to create an array argument for a specific call.
The library contains a call
SDL_RenderDrawLines(SDL_Renderer*, const(SDL_Point)*, int) //Derelict3 Binding
And I have been unable to correctly form the argument for
const(SDL_Point)*
The SDL Documentation for this function states that this argument is an array of SDL_Point, but I am unclear how to create an appropriate array to pass to this function.
Here is an example of what I have at the moment:
void DrawShape(SDL_Renderer* renderer)
{
SDL_Point a = { x:10, y:10};
SDL_Point b = { x:500, y:500};
const(SDL_Point[2]) points = [a,b];
Uint8 q = 255;
SDL_SetRenderDrawColor(renderer,q,q,q,q);
SDL_RenderDrawLines(renderer,points,1);
}
And the compiler complains that I am not passing the correct type of argument for const(SDL_Point)* in points.
Error: function pointer SDL_RenderDrawLines (SDL_Renderer*, const(SDL_Point)*, int)
is not callable using argument types (SDL_Renderer*, const(SDL_Point[2u]), int)
I suspect this is a fundamental misunderstanding on my part so any help would be appreciated.
Arrays aren't implicitly castable to pointers in D. Instead, each array (both static and dynamic) has an intrinsic .ptr property that is a pointer to its first element.
Change your code to:
SDL_RenderDrawLines(renderer,points.ptr,1);
given that the call asks for a pointer and length, I feel it is safer to define you own wrapper:
SDL_RenderDrawLines(SDL_Renderer* rend, const SDL_Point[] points){
SDL_RenderDrawLines(rend,points.ptr,points.length);
}
(why it isn't defined I don't know, any performance hit from the extra function call is just a -inline away from being resolved)

c++ class function aliases

I was wondering if there was a simple way to write an alias of a c++ class function. For instance, if I have some list container object, a logical function would be
int list::length() { return len; }
But another logical alias that programmers might use could be
int list::size() { return len; }
So, instead of writing both functions with their full body, is there any way to make list::size() an alias of list::length() such that it isn't a duplicate when compiled, but rather references the same function?
I've read that you can do this with #define, but I don't want to cause any confusion with other code-names somewhere totally out of scope (i.e. a 'size' variable).
I've also read that function pointers can fix it, but that isn't exactly an alias (since it has to apply de-referencing), nor can function pointers be given a declaration, giving it a confusing help-line to users (I would think), plus the confusion if ever I need to nest my code inside another object (I have to adjust the scope).
One of my guesses is, will the following be taken as a direct function alias by most optimizing compilers:
inline int list::length() { return len; }
inline int list::size() { return length(); }
Or, is there any strict 'alias' syntax for c++? (I couldn't find any - wasn't sure)
So then, what would be the most efficient way of doing this?
EDIT: I've accepted the answer simply to wrap up the question, since it's only a curiosity of mine. Anyone with good information, please add comments or answer, and I may even change my answer.
I would not use the preprocessor and #define to do this. In general preprocessor should be a last resort in C++. See this C++ FAQ on inline functions which also contains a section on the various evils of using macros of the preprocessor.
The approach I would use would be to have a function that will have several different aliases with a more complicated function and interface you would do something like the following:
int list::length(string xString, int iValue) {
int iReturnValue = 0; // init the return value
// do stuff with xString and iValue and other things
return iReturnValue;
}
Then do something like the following for an alias.
inline int list::size(string xString, int iValue) {return length(xString, iValue);}
The inline should basically just replace the alias with the actual function call.
See also this stack overflow posting Giving a function implementation more than one name. It provides some reasons why you might not want to do this.