C++。获取数据的类型名称作为类型,而不是字符串

标签 c++

在我开始之前我会把问题分成两部分:

第 1 部分:



在 C++ 中,我们可以使用 typeid 获取数据类型但它给你的数据是const char* ,我希望它返回数据的类型。

示例:

int data = 20 ; 
float data2 = 3.14 ; 
char *data3 = "hello world" ;

std::cout<< typeid(data).nam() << endl << endl ;
std::cout<< typeid(data2).nam() << endl << endl ;
std::cout<< typeid(data3).nam() << endl << endl ;

现在我有一个函数可以从 void* 获取数据,并将其转换为另一种类型:

template <typename t >
void print (void *data )
{   

    boost::any _t = static_cast<t> (data);
    cout << boost::any_cast<t> (_t) << endl << endl;
}

现在如果您知道您的数据类型,这就可以正常工作: 示例:

void *mydata = alloca(size_object) ;
void some_function_store_int_data_in_voidpointer( &mydata)
print <int> (mydata); // it's ok .

但是当你有很多不同的数据类型时,这是不切实际的,就像这样:

void somefunction(args &a , void *dest  )
{
 /*code returnd data */
}
enum args
{
_INT_ ,
_FLOAT_ , 
_CHARPOINTER_ ,
};

vector <void *test> myvector ;
myvector.resize (3) ;


void somefunction(_INT_ , myvector.at(0)  ) ;  // store int in void*
void somefunction(CHARPOINTER , myvector.at(0)  ) ;// store char* in void*
void somefunction(_FLOAT_ , myvector.at(0)  ) ;// store float in void*

print <int> (myvector.at(0));
print <char*> (myvector.at(1));
print <float> (myvector.at(2));

1 - 如果我使用这样的东西

print <typeid(myvector.at(2))> (myvector.at(2));

我得到一个错误,因为我的数据是 float 的,我把它设为 const char*

2 - 如果我的数据很少,也许我可以传递每个值的类型。还行吧。但是如果我有 100 个不同类型的值呢!

我正在寻找类似的东西:typeid但它返回的类型不是 `const char*。

第 2 部分



因为我有 avector,所以我将使用这样的 for_each 算法:

for_each ( myvector.begin() , myvector.end() , print</*what i should pass her int , float ,char* ...or what , */>);

在前面的代码中,我只能将一种类型传递给函数,因此将打印来自相同类型的数据。否则会打印出不同类型的数据,但完全错误(奇怪的格式)。

所以如果我通过 char* int数据将打印完全错误。

我该怎么做?

最佳答案

How can I do this differently?

如果您打算使用相同的函数来打印不同的数据格式,那么您可以这样做:

#include <iostream>
#include <algorithm>
#include <vector>

template <typename T> class Callback{
public:
    void operator()(const T& value) const{
        std::cout << value << std::endl;
    }
};

template <typename T> Callback<typename T::value_type> makeCallback(const T&){
    return Callback<T::value_type>();
}

int main(int argc, char** argv){
    std::vector<int> ints(20);
    std::vector<float> floats(20);

    std::fill(ints.begin(), ints.end(), 0);
    std::fill(floats.begin(), floats.end(), 0.0f);

    std::for_each(ints.begin(), ints.end(), makeCallback(ints));
    std::for_each(ints.begin(), ints.end(), makeCallback(floats));

    return 0;
}

但是,如果你想在同一个 std::vector 中存储几种不同的数据类型,那么你需要“变体”类型(如 boost::variantQVariant 或类似的),并且有没办法。


I am looking for something like: typeid but it' return the type not `const char*.

在 C++ 中,“类型”只存在于编译阶段,所以你不能返回它,因为一旦程序被编译它就不再存在了。没有“类型”,所以你不能返回它。

因此,要从对象中获取“类型”,您需要实现某种“变体”类型,它可以包含任何对象及其类型信息,并传递该“变体”类型。这种系统的一个例子是 QVariant在 Qt 4 中。

AFAIK 变体类型的实现是这样的:每种变体支持的类型都有某种表,您在该表中注册变体类必须支持的所有类型。表提供了用于创建类型、销毁类型、(反)序列化类型的函数,以及有关该类型的一个对象所需的内存量的可能信息。该表格可以包含您想要的可选信息,您可以将整个注册过程转换为宏+模板组合。如您所见,这不是编译器自动完成的事情,而是涉及很多麻烦并且必须由程序员处理的事情。此外,如果程序必须能够采用外部开发的类型(在插件中等),事情就会变得更加有趣。

由于语言限制,更好的办法是尽可能避免需要“返回类型”的情况——变体系统并不十分困难,但它们也不是很有趣,因为所有必要的完整性检查和转换。示例问题:如果将变体类型的字符串传递给一个应该接受 float 的函数,该函数是否应该尝试将字符串转换为 float ?如果转换失败,它应该崩溃/抛出异常,还是假设变量有默认值?如果有失败转换的默认值,它应该是什么以及应该如何传递?等等。这不是一门火箭科学,但处理起来很烦人。

例如,您可以去掉“void*”(如果函数将指针作为参数,那么我会假设 poitner 可以为 NULL/0。因此“void*”参数并不是一个好主意) .函数中的参数并使用模板使编译器为您在程序中实际使用的类型生成您想要的代码。如果模板不是一个选项,那么您需要某种“变体”类型(最好由其他人开发),......或者您可以切换到另一种提供所需类型信息的语言。您必须使用 C++,任何可以完成这项工作的工具都可以。依赖 RTTI 也不是一个完美的解决方案,因为如果您设法将指针传递给不包含类型信息的东西,您将得到一个非标准异常 ( __non_rtti_object )。

关于C++。获取数据的类型名称作为类型,而不是字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8893522/

相关文章:

c++ - 获取主板序列号

c++ - 是否可以使用 clang 自动包含缺少的 c++ 头文件?

C++ 新手 : Operation of make_shared

c++ - .def 文件 C/C++ DLL

c++ - std::initializer_list 无法从 <brace-enclosed initializer list> 推导出来

C++:从捕获函数参数的函数返回lambda表达式

c++ - 使用 MinGW、freeglut 和 glew 编译简单的静态 OpenGL 4.0 程序

c++ - 类模板特殊成员函数显式特化

c++ - 在派生类中实现插槽 - qt4/c++

c++ - 交互类 - 组织代码