C ++和动态类型语言 [英] C++ and dynamically typed languages
问题描述
今天我与朋友讨论了静态和动态类型语言之间的区别(更多关于静态和动态类型语言之间的区别的信息))。之后,我想知道什么样的伎俩可以在C ++中使用来模拟这样的动态行为。
Today I talked to a friend about the differences between statically and dynamically typed languages (more info about the difference between static and dynamic typed languages in this SO question). After that, I was wondering what kind of trick can be used in C++ to emulate such dynamic behavior.
在C ++中,与其他静态类型语言一样,变量类型在编译时指定。例如,假设我必须从一个文件中读取大量的数字,这在大多数情况下相当小,足够小以适应无符号短
类型。这里有棘手的事情,少量的这些值是更大,足够大,需要一个 unsigned long long
被存储。
In C++, as in other statically typed languages, the variable type is specified at compile time. For example, let's say I have to read from a file a big amount of numbers, which are in the majority of the cases quite small, small enough to fit in an unsigned short
type. Here comes the tricky thing, a small amount of these values are much bigger, bigger enough to need an unsigned long long
to be stored.
因为我假设我要对所有这些进行计算,我想所有这些都存储在同一个容器中的同一个我从输入文件中读取它们的顺序。。初始方法是将它们存储在 unsigned long long
类型的向量
中,但这意味着通常最多(无符号短
2字节,无符号长整型
8字节)的4倍额外空间。
Since I assume I'm going to do calculations with all of them I want all of them stored in the same container in consecutive positions of memory in the same order than I read them from the input file.. The naive approach would be to store them in a vector
of type unsigned long long
, but this means having typically up to 4 times extra space of what is actually needed (unsigned short
2 bytes, unsigned long long
8 bytes).
在动态类型语言中,变量的类型在运行时解释,并强制转换为适合的类型。 我如何在C ++中实现类似的东西?
In dynamically typed languages, the type of a variable is interpreted at runtime and coerced to a type where it fits. How can I achieve something similar in C++?
我的第一个想法是通过指针,根据它的大小,与适当的类型。这有一个明显的缺点,也必须存储指针,但由于我假设我要将它们存储在堆反正,我不认为这很重要。
My first idea is to do that by pointers, depending on its size I will store the number with the appropriate type. This has the obvious drawback of having to also store the pointer, but since I assume I'm going to store them in the heap anyway, I don't think it matters.
我完全相信很多人可以给我更好的解决方案。
I'm totally sure that many of you can give me way better solutions than this ...
#include <iostream>
#include <vector>
#include <limits>
#include <sstream>
#include <fstream>
int main() {
std::ifstream f ("input_file");
if (f.is_open()) {
std::vector<void*> v;
unsigned long long int num;
while(f >> num) {
if (num > std::numeric_limits<unsigned short>::max()) {
v.push_back(new unsigned long long int(num));
}
else {
v.push_back(new unsigned short(num));
}
}
for (auto i: v) {
delete i;
}
f.close();
}
}
编辑1:
问题不是关于保存内存,我知道在动态类型语言中,在示例中存储数字的必要空间将会超过C ++,但问题不是这样,它是关于模拟动态
Edit 1: The question is not about saving memory, I know in dynamically typed languages the necessary space to store the numbers in the example is going to be way more than in C++, but the question is not about that, it's about emulating a dynamically typed language with some c++ mechanism.
推荐答案
选项包括...
代码指定一组不同的,支持的类型T0,T1,T2,T3 ...和 - - 创建一个管理类型
The code specifies a set of distinct, supported types T0, T1, T2, T3..., and - conceptually - creates a management type to
struct X
{
enum { F0, F1, F2, F3... } type_;
union { T0 t0_; T1 t1_; T2 t2_; T3 t3_; ... };
};
因为对 union
s,如果他们被绕过使用放置 -
新
需要注意,以确保充分的对齐和正确的析构函数调用,一个广义的实现变得更复杂,通常最好使用 boost :: variant<>
。请注意, type _
字段需要一些空格, union
将至少与最大的 sizeof t0 _
, sizeof t1 _
...,可能需要填充。
Because there are limitations on the types that can be placed into union
s, and if they're bypassed using placement-new
care needs to be taken to ensure adequate alignment and correct destructor invocation, a generalised implementation becomes more complicated, and it's normally better to use boost::variant<>
. Note that the type_
field requires some space, the union
will be at least as large as the largest of sizeof t0_
, sizeof t1_
..., and padding may be required.
它也可以有一个模板化的构造函数和赋值运算符,调用 typeid
并记录 std :: type_info
,允许将来的操作,例如recover-the-value-if-it' of-a-specific-type。获取此行为的最简单方法是使用 boost :: any
。
It's also possible to have a templated constructor and assignment operator that call typeid
and record the std::type_info
, allowing future operations like "recover-the-value-if-it's-of-a-specific-type". The easiest way to pick up this behaviour is to use boost::any
.
您可以使用虚拟析构函数和所需的任何函数创建基类型(例如 virtual void output(std :: ostream&)
),然后为 short
和 long long
中的每个派生一个类。存储指向基类的指针。
You can create a base type with virtual destructor and whatever functions you need (e.g. virtual void output(std::ostream&)
), then derive a class for each of short
and long long
. Store pointers to the base class.
在您的特定场景中,几个大数字:你可以做一些事情,如保留一个 short
值为一个标记,指示在这个位置的实际值可以通过按位移位和ORing以下4个值。例如...
In your particular scenario, you've only got a few large numbers: you could do something like reserve one of the short
values to be a sentinel indicating that the actual value at this position can be recreated by bitwise shifting and ORing of the following 4 values. For example...
10 299 32767 0 0 192 3929 38
...可以编码:
10
299
// 32767 is a sentinel indicating next 4 values encode long long
(0 << 48) + (0 << 32) + (192 << 16) + 3929
38
这里的概念类似于国际字符集的UTF-8编码。这将是非常节省空间的,但它适合前向迭代,而不是随机访问索引a [123]
。
The concept here is similar to UTF-8 encoding for international character sets. This will be very space efficient, but it suits forward iteration, not random access indexing a la [123]
.
这篇关于C ++和动态类型语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!