0

Ich möchte Tausende von Interpolationsfunktionen in einem mehrdimensionalen Array speichern, vorzugsweise das von Boost. Das Hauptproblem besteht darin, dass die von mir verwendete Interpolationsfunktion eine Klasse ist, die keinen Standardkonstruktor hat. Dies verbietet mir, das mehrdimensionale Array zu initialisieren.C++, Boost, Objekte in multidimensionalem Array ohne Standardkonstruktor speichern

Was ich wünsche, dass ich tun könnte:

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; 
} 

Das Problem ist, dass die Klasse Linear_interp keinen Default-Konstruktor hat (die Klasse ähnelt dieser Klasse 1), also boost :: multi_array kann das Array nicht initialisiert werden .

Beachten Sie, dass ich alle Interpolationen innerhalb einer Schleife initialisiere und daher diese Objekte speichern muss. Ein einfacher Zeiger auf das Objekt funktioniert nicht, da das Objekt in jeder Schleife überschrieben wird.

In Wirklichkeit werde ich viel mehr Dimensionen haben (atm ich habe 10), und multi_array ist ein schöner Container, um diese zu behandeln. Außerdem werden Interpolationen in späteren Schleifen Interpolationen von vorherigen Schleifen nehmen (d. H. Ich habe ein rekursives Problem).

EDIT 1: Nebencode-Korrektur.

EDIT 2: Code Korrektur: In der vorherigen Version habe ich nicht die "y" s gespeichert, die zu unerwünschten Ergebnissen führen.

Antwort

0

Nun Zeiger funktioniert. Wenn Sie Ihr Array als:

multi_array<Linear_interp*, 2> 

deklarieren, um Zeiger auf die Objekte statt Objekte selbst zu speichern. Dann könnten Sie in der Schleife jedes Mal ein neues Objekt zuweisen und es an die entsprechende Stelle im Array setzen. Verwenden Sie einfach ein neues Schlüsselwort, um ein neues Linear_interp-Objekt innerhalb der Schleife zu erstellen. Hier ist Code in der Schleife zu verwenden:

Storage[i_x1][i_x2] = new Linear_interp(x3, y); 
+0

Vielen Dank für Ihren Kommentar. Ich bin mehr oder weniger neu in C++ und kenne mich mit dem Stichwort "new" nicht aus. Könnten Sie etwas Code mit dem schreiben, was Sie in die Schleife schreiben würden und wie ich auf ein Beispielelement zugreifen würde (wie das z in meinem Code)? – USC

+0

@USC Ich habe meine Antwort aktualisiert. – fatherOfWine

+0

Wenn ich meinen Code aktualisiere und dann versuche, den Wert (0, 1.1, 20) auszuwerten, benutze: 'printf ("% f \ n ", Speicher [0] -> interp (20))' Ich werde 24.5 bekommen, aber es sollte 21.1 sein. Es scheint, als ob die Schleife alle Elemente mit der letzten überschreibt, denn wenn ich die Ergebnisse innerhalb der Schleife drucke, bekomme ich die richtigen Ergebnisse. Erst nach der Schleife erhalte ich das Ergebnis für die allerletzte Interpolation. – USC

0

Ich bin kein Boost-Experte, aber ich bin mir sicher, dass es eine gleichwertige Lösung gibt. Sie könnten die folgenden Schritte ausführen:

Stellen Sie sicher, eine vollständige "Matrix" mit leeren innersten Arrays zu erstellen. So etwas wie die folgenden (mit std::vector) arbeitet für 3 Dimensionen:

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()); 
} 

An diesem Punkt Storage[i][j] ist eine bestehende, aber leer std::vector<Linear_interp>. So können Sie jetzt oder (::push_back mit C++ 11) verwenden, um Ihre Storage zu füllen. Gehen wir zurück auf zwei Dimensionen und Ihren ursprünglichen Code, so etwas wie dies die Arbeit machen:

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)); 
    } 
} 

push_back oder ähnliche Methoden verwenden, wird eine Kopie c'tor nur anrufen und somit für Ihre Nicht-Standard-konstruierbaren Typ arbeiten Linear_interp.