【问题标题】:Specializing function template for reference types引用类型的专用函数模板
【发布时间】:2011-01-13 07:03:28
【问题描述】:

为什么这个code的输出是:

#include <iostream>  
template<typename T> void f(T param) 
{ 
   std::cout << "General" << std::endl ; 
} 
template<> void f(int& param) 
{ 
   std::cout << "int&" << std::endl ; 
}  

int main() 
{   
  float x ;  f (x) ;   
  int y ; f (y) ;   
  int& z = y ; f (z) ; 
}  

一般
一般
一般

第三个令人惊讶,因为该函数专门针对int&amp;

编辑:我知道重载可能是一个合适的解决方案。我只是想学习它背后的逻辑。

【问题讨论】:

  • 也许是因为 const int& 比 int& 更受欢迎?
  • @Septagram: const int& ?
  • 我不知道它是否有帮助,但是如果您将模板更改为接受T &amp;,那么f(y)f(z) 都调用int &amp; 版本。
  • @Daniel Gallagher:那么您遇到了f(2); 的编译器错误。 f(y) 的输出也是int&amp;
  • 最好的办法是使用重载void f(int&amp; param)gotw.ca/publications/mill17.htm

标签: c++ templates specialization template-specialization reference-type


【解决方案1】:

表达式y 和表达式z 的类型都是int。出现在表达式中的引用不会保留引用类型。相反,表达式的类型将是引用的类型,表达式是左值。

所以在这两种情况下,T 都被推导出为int,因此根本不使用显式特化。

需要注意的重要一点(除了你应该真正使用重载,正如另一个人所说),你的模板中有一个非引用函数参数。在对参数类型进行任何T 扣除之前,参数类型将从数组转换为指向其第一个元素的指针(对于函数,参数将转换为函数指针)。因此,具有非引用函数参数的函数模板无论如何都不允许准确推导。

【讨论】:

  • +1(感谢您在我自己的回答中发现错误)
  • 关于你的第二句话:这条规则从何而来?我相信你,但你有任何来源解释这一点吗?谢谢。
【解决方案2】:

引用只是一个别名,而不是类型。所以当你调用 f(z) 时,它会匹配第一个版本与 T=int,这是一个比 T=int& 更好的选择。如果将 T 更改为 T&,则 int 和 int& 参数都将调用第二个版本。

【讨论】:

  • 如果我将 T 更改为 T&,当 f(2)f("text") 时出现编译器错误
【解决方案3】:

我知道这不是答案,但是恕我直言,您可以尝试一下,在结构中使用类似方法的特征:

template<typename T>
struct value_traits
{
    static void print(){std::cout << "General" << std::endl ;} 
};

template<>
struct value_traits<const long>
{
    static void print(){std::cout << "const long" << std::endl ;} 
};

template<>
struct value_traits<std::vector<unsigned char> >
{
    static void print(){std::cout << "std::vector<unsigned char>" << std::endl ; }
};

template<>
struct value_traits<const int>
{
       static void print(){std::cout << "const int" << std::endl ;} 
};

【讨论】:

    猜你喜欢
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多