这是问题所在:
我目前正在尝试创建一个简单的基于堆栈的编程语言(反向波兰符号,FORTH风格)作为较大项目的组成部分。不过,我遇到了障碍。
在C ++中创建堆栈(使用std::vector<>
)没有问题,该堆栈将包含一种类型的元素(例如,我可以使用语法std::vector<double> Stack
)。
但是,一种编程语言需要能够保存多种数据类型,例如整型,双精度型,字符串和3D向量(例如在具有X,Y和Z分量的物理向量中),仅举一些简单的事情。
那么,在C ++中是否有一个我可以用作堆栈的结构,该堆栈可以存储多种原始类型/对象/结构?
当然,一种方法是使用带标签的联合:
enum Type { INTEGER, DOUBLE, /* ... */ };
union Data {
uint64_t as_integer;
double as_double;
// ...
};
struct Value {
Type type;
Data data;
};
对于存储as_integer
,as_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);
}
当然,Forths通常是无类型的,这意味着堆栈仅由单词(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));
}
或者,您可以不存储值,而可以存储指向类实例的指针,该类的Value
其他值类型(例如Integer
或Double
可以从中得出)
struct Value {};
struct Integer : Value { uint64_t value; };
struct Double : Value { double value; };
// ...
您的堆栈的类型为std::vector<unique_ptr<Value>>
或std::vector<Value*>
。这样,您就不必担心值的大小不同,而以制作包装器结构并在运行时分配它们的实例为代价。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句