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

案例

现在有这样一个函数:

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

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

#include 
#include 

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

函数调用:

std::vector  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 
#include 

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

函数调用:

std::vector  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 
#include 

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

函数调用:

std::vector  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
struct typeFromContainer
{
	using type = typename Container::value_type;
};

template
struct typeFromContainer
{
	using type = T;
};

template
struct typeFromContainer
{
	using type = T;
};

函数修改为:

#include 
#include 

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

测试代码为:

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

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

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

    std::array  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  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

参考

std::begin()

std::decay

你可能感兴趣的:(#编程技巧,c++)