非类型参数模板.为什么是全局和引用

Non-type parameter templates. Why global and reference?

本文关键字:全局 引用 为什么 类型参数      更新时间:2023-10-16
template<typename Body>
Body solve(Body a, Body b){
    Body zero(0);
    return zero;  
}
template<typename Body, Body& zero>
Body solve(Body a, Body b){
    return zero;
}
complex<double> zero(0);
int main() {
    complex<double> c1(1,2);
    complex<double> c2(3,4);    
    solve<complex<double>, zero_complex> (c1,c2);
    return 0;
}

嗨,我编译了上面的代码,它是OK的(我省略了细节在这里)。现在,我注意到zero必须是一个全局变量,而且模板必须通过引用获得zero。否则会导致编译错误。我使用c++11。

请告诉我为什么一定是这样:

  1. 通过引用
  2. 传递全局变量

指向模板的指针形参和引用形参的目的是允许你编写函数(或类),它们的不同之处在于它们所使用的全局状态。

它们所使用的状态的位置成为它们类型(或名称)的一部分,必须在编译/链接/加载时确定。

局部变量(在堆栈上)有一个不同的位置——而不是一个常量。无法在编译/链接/加载时确定位置。

标准还限制了可以作为模板参数传递的字面值。这背后的原因之一是,所讨论的符号的链接时间名称成为其非类型参数的函数:并且以唯一的方式命名Body的每个实例很难

为了避免这个问题,它们只允许有限的一组值作为非类型模板形参传递:引用、指针和整型值。

可能double的问题是编译时和运行时的双精度和行为可能不同,这将使行为标准化变得棘手。所以,标准就禁止了double和float。

一种常用的技术是用无状态函子替换常量。所以你传递一个"Body函子"而不是Body常量。

函子是无状态的,并且有一个返回Bodyconst operator()

您可以使用引用作为模板参数,这就是您在这里所做的。但是,您引用的变量必须具有外部链接,而局部变量根本没有任何链接。

其他可以使用的非类型模板实参是指针和整型,如int。你的同样的例子可以这样写:

template<typename Body>
Body solve(Body a, Body b){
    Body zero(0);
    return zero;  
 }
template<typename Body, Body* zero>
   Body* solve(Body a, Body b){
   return zero;
}
int i = 0;
int main() {
  solve<int, &i>(10, 20);
}