问题
I want to store thousands of interpolation functions in a multidimensional array, preferable the one from boost. The main problem is that the interpolation function I use is a class that does not have a default constructor. This prohibits me to initialize the multidimensional array.
What I wish I could do:
double func(const double& x1, const double& x2, const double& x3)
{
return x1 + x2 + x3;
};
int main()
{
std::vector<double> x1 {0, 1, 2, 3};
std::vector<double> x2 {1.1, 1.2, 1.3, 1.4, 1.5};
std::vector<double> x3 {0, 10, 20, 30, 40};
std::vector<double> y(20, std::vector<double>(5));
boost::multi_array<Linear_interp, 2> Storage(boost::extents[4][5]);
typedef std::vector<double>::size_type vd_sz;
int n = 0;
for (vd_sz i_x1 = 0; i_x1 < x1.size(); ++i_x1) {
for (vd_sz i_x2 = 0; i_x2 < x2.size(); ++i_x2) {
for( vd_sz i_x3 = 0; i_x3 < x3.size(); ++i_x3) {
y[n][i_x3] = func(x1[i_x1], x2[i_x2], x3[i_x3]);
}
Linear_interp myInterp(x3, y);
Storage[i_x1][i_x2] = myInterp;
++n;
}
}
// Sample usage
double z = Storage[3][2].interp(23);
return 0;
}
The problem is that the class Linear_interp has no default constructor (the class is similar to this class 1), therefore boost::multi_array can not initialize the array.
Note that I initialize all interpolations inside a loop and therefore, I need to store these objects. A simple pointer to the object will not work, since the object will be overwritten in each loop.
In reality, I will have much more dimensions (atm I have 10), and multi_array is a nice container to handle these. Additionally, Interpolations in later loops, will take interpolations from previous loops (i.e. I have a recursive problem).
EDIT 1: Minor code correction.
EDIT 2: code correction: in the previous version, i did not save the "y"s which lead to unwanted results.
回答1:
Well pointer WILL work. If you will declare your array as:
multi_array<Linear_interp*, 2>
to store pointers to the the objects instead of objects themselves. Then in the loop you could allocate new object each time it would be necessary and put it to the appropriate place in the array. Just use new keyword to create new Linear_interp object inside the loop. Here is code to use inside the loop:
Storage[i_x1][i_x2] = new Linear_interp(x3, y);
回答2:
I'm not a boost expert, but I'm sure there is an equivalent solution. You could do the following steps:
Make sure to build a complete "matrix" with empty innermost arrays. Something like the following (using std::vector
) works for 3
dimensions:
std::vector<std::vector<std::vector<Linear_interp>>> Storage;
Storage.resize(x1.size());
for (vd_sz i_x1 = 0; i_x1 < x1.size(); i_x1++) {
Storage[i_x1].resize(x2.size());
}
At this point, Storage[i][j]
is an existing, but empty std::vector<Linear_interp>
. So now you can use std::vector::emplace_back
or (::push_back
with C++11) to fill your Storage
. Going back to two dimensions and your original code, something like this will do the job:
typedef std::vector<double>::size_type vd_sz;
for (vd_sz i_x1 = 0; i_x1 < x1.size(); i_x1++) {
for (vd_sz i_x2 = 0; i_x2 < x2.size(); i_x2++) {
for( vd_sz i_x3 = 0; i_x3 < x3.size(); i_x3++) {
y[i_x3] = func(x1[i_x1], x2[i_x2], x3[i_x3]);
}
Storage[i_x1][i_x2].emplace_back(x3, y);
// or: Storage[i_x1][i_x2].push_back(Linear_interp(x3, y));
}
}
Using push_back
or similar methods, will only call a copy c'tor and hence work for your non-default-constructible type Linear_interp
.
来源:https://stackoverflow.com/questions/38306335/c-boost-store-objects-in-multidimensional-array-without-default-constructor