引入
有时候,把字符串传递给函数模板的引用参数会导致错误:由于长度的区别,这些字符串属于不同的数组类型。即apple
和peach
属于char const[6]
, 而peacha
属于char const[7]
解决方法是声明为非引用参数:对于非引用类型的参数,在实参演绎的过程中,会出现数组到指针的类型转换(这种转型被称为decay)
#include <string>
#include <iostream>
// 引用传参
template <typename T>
inline T const& maxref (T const& a, T const& b)
{
return a < b ? b : a;
}
//非引用传参
template <typename T>
inline T maxnoref(T a, T b){
return a < b ? b : a;
}
int main(void)
{
std::string s;
::maxref ("apple", "peach"); // ok:相同的类型
::maxref ("apple", "peacha"); // error, 不同类型的实参
::maxref ("apple", s); // error,不同类型的实参
::maxnoref ("apple", "peach"); //ok:相同的类型
::maxnoref ("apple", "peacha"); //ok:退化为相同的类型
::maxnoref ("apple", s); // error,不同类型的实参
}
关于类型转换
#include <string>
#include <iostream>
#include <typeinfo>
// 引用传参
template <typename T>
void ref (T const& x)
{
std::cout << "x in ref(T const&): "
<< typeid(x).name() << '\n';
}
template <typename T>
void nonref (T x)
{
std::cout << "x in nonref(T): "
<< typeid(x).name() << '\n';
}
int main(void)
{
ref("hello");
ref("helloaq");
nonref("hello");
nonref("helloaq");
}
怎么解决
没有通用的解决方法,根据不同的情况,采用下面不同的方法:
- 使用非引用参数,取代引用参数(然而,这可能会导致无用的拷贝)
- 编写接受引用参数和非引用参数的重载(可能导致二义性)
- 对具体类型重载
- 强制要求使用显示类型转换
- 重载数组类型,比如:
#include <string>
#include <iostream>
template<typename T, int N, int M>
inline T const *maxref(T const (&a)[N], T const (&b)[M]){
return a < b ? b : a;
}
int main(void)
{
std::string s;
::maxref ("apple", "peach"); // ok:相同的类型
::maxref ("apple", "peacha"); // ok
::maxref ("apple", s); // error,不同类型的实参
}
总结
对于字符串,在实参演绎过程中,当且仅当参数不是引用时,才会出现数组到指针的类型转换