Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pass an array with different sizes to my c++ function?

I'm not sure if this is possible but i'm open to ideas.

I have a c++ function. It does some calculation to arrays that are being defined by users as inputs and will generate two output values. Let's call it "myfunction" and it looks something like this:

void myfunction(double array1[18],double array[9],double array [2],double *output1, double *output2)

I want to make this function more generic so that it is able to take in arrays of different size. Meaning, I want users of this function to be able to define array inputs of other size.

For example,

void myfunction(double array1[81],double array[27],double array [3],double *output1, double *output2)

Mathematically, "myfunction" is able to calculate accurate outputs despite the array size. I don't want to make a duplicate of "myfunction" because there are a total of 5 different sets of array size that the user can define as inputs.

Any ideas? thank you in advance

like image 433
umz Avatar asked Dec 14 '22 14:12

umz


2 Answers

You can either pass a std::vector or use a template:

template <std::size_t N1, std::size_t N2, std::size_t N3> // and so on...
void work_with_arrays(double (&arr1)[N1], double (&arr2)[N2], double (&arr3)[N3]){
    std::cout << "First arr of a size: " << N1 << "\n";
    std::cout << "Second arr of a size: " << N2 << "\n";
    std::cout << "Third arr of a size: " << N3 << "\n";
};

int main() {
    double something[32];
    double fewer[13];
    double maybe_byte[8];

    work_with_arrays(something, fewer, maybe_byte);
}

The code outputs:

First arr of a size: 32
Second arr of a size: 13
Third arr of a size: 8

Explanation:

One should know that the argument of type T[] (T being any type) decays to T*. If we're dealing with a pointer to an array, we have no information about its length, which is quite unfortunate, given the fact that lengths of fixed-length arrays are known at compile time and could be visible everywhere we work with them.

One should also know that a function template is not a function. It is a template used to create functions. For every different set of N# used in the example above, there will be a function generated for our use.

What is the workaround to the decaying problem?

Instead of passing a raw T[], we should pass a reference to T[]. That way the type does not decay and the size of the array will be known.

Syntax?

One could notice that T (&name)[some_size] looks at least bizarre. The parentheses are required, since plain T &name[size] would be interpreted as T& name[size], which is an array of references, not a reference to an array.

Conclusion:

Being able to detect the size of a passed-as-argument array, we don't want to limit ourselves with one or two cases - we want to cover them all, so we use a template to generate functions with N# of needed value.

like image 106
Fureeish Avatar answered Dec 26 '22 00:12

Fureeish


You can have your function take in a vector which is a "dynamically resizable array". You can iterate over it, or get its size as needed. See its docs.

#include <vector>
using std::vector;  // I'm too lazy to prepend std:: as needed.
void myfunction(const vector<double>& array1, 
                const vector<double>& array2,
                const vector<double>& array3, 
                vector<double>& output1, vector<double>& output2) {

}

If that is not possible, then have it take in extra arguments indicating the size of the arrays.

void myfunction(double *array1,
                double *array2, 
                double *array3,
                int size1,
                int size2,
                int size3,
                double *output1, 
                double *output2) {

}

but this is really ugly. Just go with the first option.

like image 23
lightalchemist Avatar answered Dec 25 '22 22:12

lightalchemist