C ++ Stapel für mehrere Datentypen (RPN Vektorrechner)
Frage
Ich habe eine schnelle und einfache Vektorarithmetik-Bibliothek in C ++ entwickelt. Ich nenne das Programm von der Befehlszeile, wenn I ein schnelles Quer Produkt benötigen, oder dem Winkel zwischen den Vektoren. Ich benutze Matlab oder Octave oder verwandte nicht, weil die Startzeit größer als die Rechenzeit ist. Auch dies für sehr einfache Operationen ist.
Ich Erweiterung dieses Programm, und ich werde es als RPN-Rechner arbeiten machen, für den Betrieb des Typs:
1 2 3
4 5 6
x
out: -3 6 -3
(geben einen Vektor, einen anderen Vektor, und das „Kreuz“ -Operator; auszuspucken dem Kreuzprodukt)
Der Stapel muss 3D-Vektoren oder Skalare akzeptieren, für Operationen wie:
1 2 3
2
*
out: 2 4 6
Der Lexer und Parser für diesen Mini-Rechner sind trivial, aber ich kann nicht für die Erstellung des internen Stack zu denken, eine gute Art und Weise zu sein scheint. Wie würden Sie einen Stapel für enthaltenden Vektoren oder Doppel (I gerollten meine eigene sehr einfache Vektorklasse - weniger als hundert Zeilen und es tut alles, was ich brauche) erstellen.
Wie kann ich einen einfachen Stapel erstellen, die Elemente der Klasse Vector akzeptiert oder geben Doppelten?
Danke.
Lösung
Der einfachste Weg wäre nur eine Operand
Struktur zu schaffen, die eine double
für die skalare und ein Vector
Objekt für den Vektor enthält:
struct Operand
{
double scalar_;
Vector vector_;
bool isVector_;
};
(Sie isVector_
auf true gesetzt, wenn es ein Vektor-Operanden, und falsch, wenn es sich um ein Skalaroperand ist)
Für den eigentlichen Stack, können Sie einfach std::stack<Operand>
verwenden.
Weitere Optionen sind Vererbungs (Erstellen von Skalar und Vektortypen von einem Operanden-Basistyp abgeleitet) oder so etwas wie boost::variant
, aber für etwas Einfaches wie diese, eine Zusammensetzung Struktur wie die Operand
oben gezeigt ist wahrscheinlich der einfachste Weg, es zu tun.
Andere Tipps
Haben Sie sich unter boost :: any ?
Eine Lösung ist die Verwendung Gewerkschaften. Mit Gewerkschaften können Sie gleichen den Speicherbereich für verschiedene Strukturen verwenden. Zum Beispiel können Sie ein Doppel und ein struct in der Vereinigung haben. Sie teilen sich den gleichen Speicher und Sie können nur eine von ihnen. Sie können einige ENUM nutzen zu sagen, welche zu benutzen.
Die Gewerkschaften sind ein wenig hacky, weil sie Verwendung von Objekten kniffliger machen. Compiler weiß nicht, wie zu konstruieren, zu zerstören oder kopieren Sie sie, weil viele Objekte den gleichen Speicher gemeinsam nutzen können. Hier ist ein kleines Beispiel, wie ich dies tun würde, wenn ich Speicher speichern möchten (okay, Enum dauert vier Bytes und ist somit nicht Speicher effizient, aber lassen wir das vergessen;)
#include <cstdlib>
#include <iostream>
struct Vector
{
double x, y, z;
};
struct Element
{
enum Type { SCALAR, VECTOR };
Type type;
union {
double scalar;
Vector v;
} data;
};
int main(void)
{
Element vector_element;
vector_element.type = Element::VECTOR;
vector_element.data.v.x = 1;
vector_element.data.v.y = 2;
vector_element.data.v.z = 3;
Element scalar_element;
scalar_element.type = Element::SCALAR;
scalar_element.data.scalar = 3.142;
std::cout << "The size of type Element without enum would be: " << (sizeof(Element) - sizeof(Element::Type)) << " bytes." << std::endl;
return EXIT_SUCCESS;
}
Durch die Art und Weise, aus irgendeinem seltsamen Grund, diese Ergebnisse zu 28 Bytes. Ich erwartete 3 * 8 = 24 Bytes.