现在的位置: 首页 > 综合 > 正文

字符串传递给函数模板的引用参数出现出人意料的结果

2013年10月11日 ⁄ 综合 ⁄ 共 1383字 ⁄ 字号 评论关闭
Code:
  1. #include <string>   
  2. // 注意:使用 reference parameters   
  3. template <typename T>   
  4. inline T const& max (T const& a, T const& b)   
  5. {   
  6.     return a < b ? b : a;   
  7. }   
  8. int main()   
  9. {   
  10.     std::string s;   
  11.     ::max("apple","peach"); // OK:类型相同   
  12.     ::max("apple","tomato"); // ERROR:类型不同   
  13.     ::max("apple",s); // ERROR:类型不同   
  14.     return 0;   
  15. }  

上面的代码是C++ template 5.6中的程序,David详细的解释了为什么会这样的原因:

问题出在这几个字符串字面常数(string literals)的长度不同,因而其底层的 array 类型也不
同。
换句话说 "apple" 和 "peach" 的 array 类型都是 char const[6],而 "tomato" 的 array
型 别是 char const[7]。上述调用只有第一个合法,因为两个参数具有相同类型;然而如果你
使
用 by value 传递方式,就可以传递不同类型的字符串字面常数(string literals),其对应的 array
大小不同:

Code:
  1. // basics/max6.hpp   
  2. #include <string>   
  3. // 注意:使用 non-reference parameters   
  4. template <typename T>   
  5. inline T max(T a, T b)   
  6. {   
  7. return a < b ? b : a;   
  8. }   
  9. int main()   
  10. {   
  11. std::string s;   
  12. ::max("apple","peach"); // OK:类型相同   
  13. ::max("apple","tomato"); // OK:退化为相同类型   
  14. ::max("apple",s); // 错误:类型不同   
  15. }  

这种方式之所以可行,因为在自变量推导过程中,惟有当参数并不是一个 reference 类型时,「array
转为 pointer」的转型动作(常被称为退化, decay)才会发生。这个规则可藉以下例子加以说明:

Code:
  1. // basics/refnonref.cpp   
  2. #include <typeinfo>   
  3. #include <iostream>   
  4. template <typename T>   
  5. void ref (T const& x)   
  6. {   
  7. std::cout << "x in ref(T const&): "  
  8. << typeid(x).name() << std::endl;   
  9. }   
  10. template <typename T>   
  11. void nonref (T x)   
  12. {   
  13. std::cout << "x in nonref(T): "  
  14. << typeid(x).name() << std::endl;   
  15. }   
  16. int main()   
  17. {   
  18. ref("hello");   
  19. nonref("hello");   
  20. }  

详细见C++ template the complete guide

抱歉!评论已关闭.