C ++ stack per più tipi di dati (RPN calcolatrice vettore)
Domanda
Ho progettato una biblioteca aritmetica vettoriale rapido e di base in C ++. Chiamo il programma dalla riga di comando quando ho bisogno di un prodotto trasversale rapido, o angolo tra vettori. Non faccio uso di Matlab o Octave o correlate, in quanto il tempo di avvio è più grande del tempo di calcolo. Ancora una volta, questo è per le operazioni di base.
sto estendendo questo programma, e io farlo funzionare come un calcolatore RPN, per le operazioni del tipo:
1 2 3
4 5 6
x
out: -3 6 -3
(indicare un vettore, un altro vettore, e l'operatore "croce", sputare il prodotto vettoriale)
La pila deve accettare vettori o scalari 3D, per le operazioni come:
1 2 3
2
*
out: 2 4 6
Il lexer e parser per questo mini-calcolatrice sono banali, ma io non riesco a pensare ad un buon modo per creare la pila interna. Come si creerebbe una pila di per contenere vettori o doppie (mi sono rimboccato la mia classe molto semplice vettore - meno di cento righe e fa tutto quello che ho bisogno).
Come posso creare un semplice pila che accetta elementi della classe Vector o di tipo double?
Grazie.
Soluzione
Il modo più semplice sarebbe solo di creare una struct Operand
che contiene un double
per lo scalare e un oggetto Vector
per il vettore:
struct Operand
{
double scalar_;
Vector vector_;
bool isVector_;
};
(È possibile impostare isVector_
a true se si tratta di un vettore operando, e falso se si tratta di un operando scalare)
Per lo stack effettivo, si può semplicemente utilizzare std::stack<Operand>
.
Altre opzioni includono eredità (la creazione di tipi scalari e vettoriali derivate da un tipo di base di operando) o qualcosa di simile boost::variant
, ma di qualcosa di semplice come questo, una struttura composizione come la Operand
mostrato sopra è probabilmente il modo più semplice per farlo.
Altri suggerimenti
Hai guardato boost :: qualsiasi ?
Una soluzione è quella di utilizzare i sindacati. Con i sindacati, è possibile utilizzare lo stesso l'area di memoria per le diverse strutture. Ad esempio, si può avere uno struct matrimoniale e una in unione. Essi condividono la stessa memoria ed è possibile utilizzare solo uno di loro. È possibile utilizzare alcuni enum per dire quale usare.
I sindacati sono un po 'hacky, perché fanno uso di oggetti più complicato. Compilatore non sa come costruire, distruzione o copiare loro, perché molti oggetti possono condividere la stessa memoria. Ecco un piccolo esempio di come avrei fatto questo se mi piacerebbe risparmiare memoria (ok, enum prende quattro byte e quindi non è efficiente della memoria, ma cerchiamo di dimenticare che;)
#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;
}
A proposito, per qualche strana ragione, questo si traduce a 28 byte. Mi aspettavo 3 * 8 = 24 byte.