如何使用typeinfo.name C ++声明变量

时间:2018-12-30 07:43:15

标签: c++ auto decltype typeinfo

我喜欢编码,并且由于其简单性和强大功能,通常在Python中也是如此。
但是,对于一些时间紧迫的程序/任务,我使用C ++。
因此,为了两全其美,我在C ++中列出了Pythonesque。

AIM:我希望能够添加任何数据类型的任何变量或值,包括用户定义的类
为此,我有一个结构item,其中有一个char * value,一个char * type和一个int size
我的List具有这些item *的数组。


现在,我已将变量包含在模板函数中:
template<class T> item * encode(const T& var);
并声明了指向项目item * i = new item;

的指针

而且,我将这些变量的值存储为c样式字符串。
例如,二进制文件中的146750000 0000 0000 0000 0011 1001 0101 0011
因此,我已经动态创建了空间,如下所示:
i->size = sizeof(var);
i->value = new char[i->size]; //4 in this case
 并用var中的各个位设置值中的每个位。

我也将它们的类型存储为
i->type = typeinfo(var).name();
到目前为止一切顺利!


现在,我被auto decode(item * i) -> decltype(/*What goes here???*/)困住了
如何指定函数的返回类型?
有什么办法吗?
最好使用i->type
还是应该更改此过程的基本设计?
预先感谢!

1 个答案:

答案 0 :(得分:0)

回答您的问题

  

我希望能够添加任何数据类型的任何变量或值,包括用户定义的类。

没有用户的合作,这在C ++中是不可能的。

请记住,C ++类型仅是编译时概念。它们在运行时不存在。在运行时唯一可用的类型信息是typeid()提供的RTTI薄层。像Python中那样的运行时鸭子输入是不可能的。

您可以很容易地创建一个包含任意对象的容器。

std::vector<std::any> v;  // requires C++17

但是该容器的用户必须知道哪个索引包含什么类型:

if (v[0].type() == typeid(ArbitraryUserType)) {
    const auto& item = std::any_cast<ArbitraryUserType>(v[0]);
    // work on item ...
}

由于类型的编译时性质,您作为库编写器无法执行该any_cast。必须在用户的源代码中说明。

通常,不要试图将Python的思维模式塞入C ++ 。它永远不会完结,尤其是当您尝试规避C ++最基本的基础之一:其强大的静态类型系统时。

注意:

  • 没有C ++ 17,您可以使用boost::any
  • 如果您知道在编译时可能的类型列表,std::vector<std::variant<Type1, Type2, etc>>是一个很好的选择。使用any,用户完全有责任跟踪其类型。因为所有类型检查都在运行时发生,所以编译器无法提供帮助。另一方面,Variant带来了大量的编译时安全性。还有boost::variant作为非C ++ 17的替代方案。

关于编码方式的注意事项

基本上,您正在尝试序列化(编码)和反序列化(解码)任意类型。没有这些类型的合作,这是不可能的。

您的方法仅适用于可以一点一点复制的琐碎类型。 C ++甚至具有以下类型特征:std::is_trivially_copyable。最后,您支持这些基础类型和C样式结构,但仅此而已。

想象一下,您的T函数的encode()std::string。只需放置一个std::string包含一个指向单独分配的内存的指针,该内存就会存储实际的字符串数据。字符串对象本身只是该指针的管理包装。 encode()仅序列化包装对象,而不对具有实际数据的指向的存储块进行序列化。

即使在反序列化期间您可以从位流中实例化任意类型,该流也不完整。您需要实现的是Python copy.deepcopy的C ++版本,没有每种类型的合作就不可能实现。看看C ++序列化库-以Cereal作为简单示例-看看这种合作在实践中如何看待。