通过容器(数组)类型萃取元素类型
- 用GetEleType类模板进行常规实现
#include <iostream>
#include <vector>
#include <list>
// 泛化版本
template<typename T>
struct GetEleType;
// 特化版本
template<typename T>
struct GetEleType<std::vector<T>>
{
using type = T;
};
// 特化版本
template<typename T>
struct GetEleType<std::list<T>>
{
using type = T;
};
template<typename T,std::size_t Size> // 这个特化版本增加了一个模板参数
struct GetEleType<T[Size]> // 萃取出数组元素个数
{
using type = T;
static const std::size_t size = Size;
};
int main()
{
std::cout << "vector<double>的元素类型为:" << typeid(GetEleType<std::vector<double> >::type).name() << std::endl;
std::cout << "list<int>的元素类型为:" << typeid(GetEleType<std::list<int> >::type).name() << std::endl;
std::cout << "float[45]的元素类型为:" << typeid(GetEleType<float[45]>::type).name() << std::endl;
std::cout << "float[45]的数组元素数量为:" << GetEleType<float[45]>::size << std::endl;
return 0;
}
这个数组、vector
、list
的元素类型萃取,还是很有意思的
- 引入函数模板
PrintEleTyp
#include <iostream>
#include <vector>
#include <list>
// 泛化版本
template<typename T>
struct GetEleType;
// 特化版本
template<typename T>
struct GetEleType<std::vector<T>>
{
using type = T;
};
// 特化版本
template<typename T>
struct GetEleType<std::list<T>>
{
using type = T;
};
template<typename T,std::size_t Size> // 这个特化版本增加了一个模板参数
struct GetEleType<T[Size]> // 萃取出数组元素个数
{
using type = T;
static const std::size_t size = Size;
};
template<typename T>
void PrintEleType(const T& container)
{
std::cout << "容器[数组]的元素类型为:" << typeid(GetEleType<T>::type).name() << std::endl;
}
int main()
{
std::vector<double> my_vec_double;
PrintEleType(my_vec_double);
std::list<int> my_list_int;
PrintEleType(my_list_int);
float my_array_float[45];
PrintEleType(my_array_float);
int a = 5;
std::cout << typeid(a).name() << std::endl;
return 0;
}
获取一个数据的类型,从此拨云开雾,成了一个简单的乐趣
GetEleType
类模板的改进
无论是std::vetor
还是std::list
,其内部都定义了该容器对应的元素类型,代码大概类似如下:
template<class T>
struct vector
{
// ...
using value_type = T;
};
所以,其实是可以直接获取std::vector
容器中的元素类型。
std::cout << "vector<double>的元素类型为:"<<
typeid(std::vector<double>::value_type).name() << std::endl;
也可以改造一下GetEleType
类模板,为泛化版本增加定义,取消针对容器的特化版本,改造后如下:
#include <iostream>
#include <vector>
#include <list>
泛化版本
//template<typename T>
//struct GetEleType;
//
特化版本
//template<typename T>
//struct GetEleType<std::vector<T>>
//{
// using type = T;
//};
//
特化版本
//template<typename T>
//struct GetEleType<std::list<T>>
//{
// using type = T;
//};
//
//
//template<class T>
//struct vector
//{
// // ...
// using value_type = T;
//};
// 泛化版本,用泛化版本实现对容器类型的支持
template<typename T>
struct GetEleType
{
using type = typename T::value_type; // 针对容器
};
// 针对数组的特化版本内容不变
template<typename T,std::size_t Size>
struct GetEleType<T[Size]>
{
using type = T;
static const std::size_t size = Size;
};
// 别名模板:真强大,加一层,直接从(GetElType<T>::type 省为 EleType<T>)
// 这不就是把复杂的事情简单化吗,高手中的高手
template<typename T>
using EleType = typename GetEleType<T>::type;
template<typename T>
void PrintEleType(const T& container)
{
// std::cout << "容器(数组)的元素类型为:" << typeid(GetEleType<T>::type).name() << std::endl;
std::cout << "容器[数组]的元素类型为:" << typeid(EleType<T>).name() << std::endl;
}
int main()
{
std::vector<double> my_vec_double;
PrintEleType(my_vec_double);
std::list<int> my_list_int;
PrintEleType(my_list_int);
float my_array_float[45];
PrintEleType(my_array_float);
int a = 5;
std::cout << typeid(a).name() << std::endl;
return 0;
}
这个代码的运行结果,事实胜于雄辩,解释了标准库容器源码中using value_type = T;
的存在。