从C++容器中获取存储数据的类型

2023-12-27 23:35:05

案例

现在有这样一个函数:

template <typename Container>
void  func(Container  t, const char* pMessage){ }

需要从容器 t 中获取元素的类型,首先我们想到的是:?

#include <iostream>
#include <boost/type_index.hpp>

template <typename Container>
void ?func(Container& t, const char* pMessage) 
{
    using TYPE = decltype(*t.begin());
    std::cout << pMessage << boost::typeindex::type_id_with_cvr<decltype(TYPE)>().pretty_name() << std::endl;
}

函数调用:

std::vector<int>  array4;
func(array4, "array4 value type is: ");  //编译正确

int array1[5] = {0, 1,3,4,8};
func(array1, "array1 value type is: ");  //编译报错

屏蔽编译错误,输出:

array4 value type is: int&

如果需要定义跟t中元素一样类型的变量, 如:

TYPE ?temp;

编译报错, 那是因为TYPE是int&,如果需要定义,就必须去掉引用,于是想到了std::decay, 它的作用是取出基本类型, 为类型T应用从左值到右值(lvalue-to-rvalue)、数组到指针(array-to-pointer)和函数到指针(function-to-pointer)的隐式转换。转换将移除类型T的cv限定符(const和volatile限定符),上面的代码就可以这样写:

#include <iostream>
#include <boost/type_index.hpp>

template <typename Container>
void ?func(Container& t, const char* pMessage) 
{
    using TYPE = std::decay<decltype(*t.begin())>;
    std::cout << pMessage << boost::typeindex::type_id_with_cvr<decltype(TYPE)>().pretty_name() << std::endl;
}

函数调用:

std::vector<int>  array4;
func(array4, "array4 value type is: ");  //编译正确

int array1[5] = {0, 1,3,4,8};
func(array1, "array1 value type is: ");  //编译还是报错

屏蔽编译错误,输出:

array4 value type is: int

此时函数调用func(array1, "array1 value type is: ")还是报错,主要是func没有考虑容器是数组的情况,利用C++11之后系统提供的std::begin()就可以满足要求,于是代码修改如下:

#include <iostream>
#include <boost/type_index.hpp>

template <typename Container>
void ?func(Container& t, const char* pMessage) 
{
    using TYPE = std::decay<decltype(*std::begin(t)>;
    std::cout << pMessage << boost::typeindex::type_id_with_cvr<decltype(TYPE)>().pretty_name() << std::endl;
}

函数调用:

std::vector<int>  array4;
func(array4, "array4 value type is: ");  //编译正确

int array1[5] = {0, 1,3,4,8};
func(array1, "array1 value type is: ");  //编译正确

输出:

array4 value type is: int
array1 value type is: int

解决方法

上面的代码都是基于C++标准容器的,从std::begin()可以联想到STL中标准容器中有个value_type,可以直接拿来使用,于是先定义个类型萃取器:

template<typename Container>
struct typeFromContainer
{
	using type = typename Container::value_type;
};

template<typename T, size_t N>
struct typeFromContainer<T[N]>
{
	using type = T;
};

template<typename T>
struct typeFromContainer<T[]>
{
	using type = T;
};

函数修改为:

#include <iostream>
#include <boost/type_index.hpp>

template <typename Container>
void ?func(Container& t, const char* pMessage) 
{
    using type = typename typeFromContainer<Container>::type;
    std::cout << pMessage << boost::typeindex::type_id_with_cvr<decltype(TYPE)>().pretty_name() << std::endl;
}

测试代码为:

int  main()
{
    std::vector<int>  array4;
    func(array4, "array4 value type is: "); 

    int array1[5] = {0, 1,3,4,8};
    func(array1, "array1 value type is: "); 

    std::initializer_list<int>  intArray{ 9, 10, 33,44 };
    func(intArray, "intArray value type is: ");

    std::array<int, 5>  arArray{ 1,2,555,666,777888 };
    func(arArray, "arArray value type is: ");

    std::string  strArray("32095235252");
    func(strArray, "strArray value type is: ");  

    const int array2[6] = { 2,3,4,5,6,7 };
    func(array2, "array2 value type is: "); 

    std::list<int>  list1;
    func(list1, "list1 value type is: "); 
    
    return 0;
}

输出:

array4 value type is: int
array1 value type is: int
intArray value type is: int 
arArray value type is: int
strArray value type is: char
array2 value type is: const int
list1 value type is: int

文章来源:https://blog.csdn.net/haokan123456789/article/details/135251777
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。