如何使用具有多种数据类型的c ++堆栈

Sta*_*cer 5 c++ string stack vector variant

这是问题所在:

我目前正在尝试创建一个简单的基于堆栈的编程语言(反向波兰表示法,FORTH样式)作为更大项目的组件.不过,我遇到了麻烦.

在c ++(通过使用std::vector<>)中创建一个包含一种类型元素的堆栈没有问题(例如,我可以使用语法std::vector<double> Stack).

但是,编程语言需要能够保存多种数据类型,例如整数,双精度,字符串和三维向量(如在具有X,Y和Z分量的物理向量中),仅举几个简单的事情.

那么,C++中是否有一个构造可以用作堆栈,它可以存储多种基本类型/对象/结构?

Jon*_*rdy 5

当然,一种方法是使用标记联合:

enum Type { INTEGER, DOUBLE, /* ... */ };

union Data {
    uint64_t as_integer;
    double as_double;
    // ...
};

struct Value {
    Type type;
    Data data;
};
Run Code Online (Sandbox Code Playgroud)

对于存储as_integeras_double等会重叠,所以Value结构会占用存储的两个词,而你的筹码将有类型std::vector<Value>。然后data根据 的值访问成员type

void sub(std::vector<Value>& stack) {
    // In reality you would probably factor this pattern into a function.
    auto b = stack.back();
    stack.pop_back();
    assert(b.type == INTEGER);

    auto a = stack.back();
    stack.pop_back();
    assert(a.type == INTEGER);

    Value result;
    result.type = INTEGER;
    result.data.as_integer = a.data.as_integer - b.data.as_integer;
    stack.push_back(result);
}
Run Code Online (Sandbox Code Playgroud)

当然,Forth 通常是无类型的,这意味着堆栈仅由字 ( std::vector<uint64_t>)组成,数据值的解释取决于对它进行操作的字。在这种情况下,您将通过联合或reinterpret_cast在每个单词的实现中使用适当的类型来双关语:

void subDouble(std::vector<Data>& stack) {
    // Note that this has no type safety guarantees anymore.
    double b = stack.back().as_double;
    stack.pop_back();

    double a = stack.back().as_double;
    stack.pop_back();

    Data result;
    result.as_double = a - b;
    stack.push_back(result);
}

void subDouble(std::vector<uint64_t>& stack) {
    double b = reinterpret_cast<double&>(stack.back());
    stack.pop_back();

    double a = reinterpret_cast<double&>(stack.back());
    stack.pop_back();

    double result = a - b;
    stack.push_back(reinterpret_cast<uint64_t&>(result));
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以不存储值,而是存储指向Value其他值类型(例如IntegerDouble将派生)的类实例的指针:

struct Value {};
struct Integer : Value { uint64_t value; };
struct Double : Value { double value; };
// ...
Run Code Online (Sandbox Code Playgroud)

您的堆栈将具有类型std::vector<unique_ptr<Value>>std::vector<Value*>. 然后您不必担心不同的值大小,代价是制作包装器结构并在运行时分配它们的实例。