现在有这样一个函数:
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