本文讨论模板函数的输入参数是数组的场景。按照前文的分析,首先看第一种情况,也就是模板参数是引用或者是指针,但是不是通用引用:
#include <iostream>
#include <type_traits>
template<typename T> void f(T& param)
{
using ParamType = T&;
bool TIsArray = std::is_same<T, const char[13]>::value;
bool TIsConstCharPoint = std::is_same<T, const char*>::value;
if (TIsArray) {
std::cout << "T is const char[13], ";
} else if (TIsConstCharPoint) {
std::cout << "T is const char*, ";
}
bool ParamTypeIsArrayRef = std::is_same<ParamType, const char (&)[13]>::value;
bool ParamTypeIsConstCharPointRef = std::is_same<ParamType, const char*&>::value;
if (ParamTypeIsArrayRef) {
std::cout << "param's type is const char (&)[13]\n";
} else if (ParamTypeIsConstCharPointRef) {
std::cout << "param's type is const char*&\n";
}
}
int main()
{
const char name[] = "J. P. Briggs"; // name's type is const char[13]
f(name); // T is const char[13], param's type is const char (&)[13]
return 0;
}
可以看到,推导的结果,T是数组,而ParamType是数组的引用。这个符合预期。
第二种情况,模板参数是通用引用:
#include <iostream>
#include <type_traits>
template<typename T> void f(T&& param)
{
using ParamType = T&&;
bool TIsArray = std::is_same<T, const char[13]>::value;
bool TIsArrayRef = std::is_same<T, const char (&)[13]>::value;
if (TIsArray) {
std::cout << "T is const char[13], ";
} else if (TIsArrayRef) {
std::cout << "T is const char (&)[13], ";
}
bool ParamTypeIsArrayRef = std::is_same<ParamType, const char (&)[13]>::value;
bool ParamTypeIsConstCharPointRef = std::is_same<ParamType, const char*&>::value;
if (ParamTypeIsArrayRef) {
std::cout << "param's type is const char (&)[13]\n";
} else if (ParamTypeIsConstCharPointRef) {
std::cout << "param's type is const char*&\n";
}
}
int main()
{
const char name[] = "J. P. Briggs"; // name's type is const char[13]
f(name); // T is const char (&)[13], param's type is const char (&)[13]
return 0;
}
传入的数组是左值,因此T和ParamType相同,都是数组的引用。也符合预期。
第三种情况:模板参数既不是指针,也不是引用:
#include <iostream>
#include <type_traits>
template<typename T> void f(T param)
{
using ParamType = T;
bool TIsArray = std::is_same<T, const char[13]>::value;
bool TIsConstCharPoint = std::is_same<T, const char*>::value;
if (TIsArray) {
std::cout << "T is const char[13], ";
} else if (TIsConstCharPoint) {
std::cout << "T is const char*, ";
}
bool ParamTypeIsArray = std::is_same<ParamType, const char[13]>::value;
bool ParamTypeIsConstCharPoint = std::is_same<ParamType, const char*>::value;
if (ParamTypeIsArray) {
std::cout << "param's type is const char[13]\n";
} else if (ParamTypeIsConstCharPoint) {
std::cout << "param's type is const char*\n";
}
}
int main()
{
const char name[] = "J. P. Briggs"; // name's type is const char[13]
f(name); // T is const char*, param's type is const char*
return 0;
}
这种情况,T和ParamType相同,但退化为指针。
神奇的是,可以利用模板函数推导出数组的结果,在编译时计算数组的长度:
#include <iostream>
template<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
return N;
}
int main()
{
int keyVals[] = { 1, 3, 7, 9, 11, 22, 35 }; // keyVals has 7 elements
int KeyValsArrayNum = arraySize(keyVals);
std::cout << "KeyValsArrayNum is " << KeyValsArrayNum << "\n"; // KeyValsArrayNum is 7
return 0;
}
如果,把T(&)[N]改成T(&&)[N],编译会失败,原因是这个不是通用引用,而是右值引用。