Popgalop
Popgalop

Reputation: 757

Using Stack implementation C++

I am making a toy programming language in c++, but i have run into a problem. I have noticed that in c++ a stack can only store one type of data. I was wondering if there was an easy way to fix this problem, such as by storing in the stack a byte array of each object. I was wondering if anyone knows how the jvm overcomes this issue. The types i would need to store on the stack would be char, short, int, float, double, strings, arrays, and references to objects. I understand that the jvm stack might be more of an abstraction, but if it is i would still like to know how they have accomplished it. If it makes any difference, i am only planning to target windows computers.

Upvotes: 0

Views: 179

Answers (3)

Chris Olsen
Chris Olsen

Reputation: 3471

Just a guess, but the jvm probably treats everything as an object, so the stack is simply a collection of objects.

You can do the same, if you create a base data object class and derive all your supported data types from it.

Upvotes: 0

Crowman
Crowman

Reputation: 25908

You know C++ has support for inheritance and polymorphism, right? A far easier way to do this is to derive all your tokens from a common base class, and make a stack of Base * objects, for instance:

#include <iostream>
#include <string>
#include <stack>
#include <memory>

class base {
    public:
        virtual void print_token() = 0;
        virtual ~base() {}
};

class token_a : public base {
    public:
        token_a(int n) : n(n) {}
        virtual void print_token() { std::cout << n << std::endl; }

    private:
        int n;
};

class token_b : public base {
    public:
        token_b(std::string s) : s(s) {}
        virtual void print_token() { std::cout << s << std::endl; }

    private:
        std::string s;
};

int main(void) {
    std::stack<std::shared_ptr<base> > my_stack;
    my_stack.push(std::shared_ptr<base>(new token_a(5)));
    my_stack.push(std::shared_ptr<base>(new token_b("a word")));

    for ( int i = 0; i < 2; ++i ) {
        std::shared_ptr<base> pb = my_stack.top();
        pb->print_token();
        my_stack.pop();
    }

    return 0;
}

outputs:

paul@local:~/src/cpp/scratch$ ./stack
a word
5
paul@local:~/src/cpp/scratch$

Upvotes: 3

Mats Petersson
Mats Petersson

Reputation: 129314

The way I have solved this problem (in C, for a lisp interpretr, about 25 years ago, but same idea applies today) is to have a struct with a type and a union inside it:

struct Data   // or class
{
    enum kind { floatkind, intkind, stringkind, refkind };
    Kind kind;
    union
    {
       double f;
       int i;
       std::string s;
       Data* r;     // reference, can't use Data &r without heavy trickery. 
    } u;

    Data(double d) { kind = floatkind; u.f = d; }
    Data(int i) { kind = intkind; u.i = i; }
    ... 
}

std::stack<Data> st;

st.push(Data(42));
st.push(Data(3.14));

Upvotes: 2

Related Questions