非类型参数模板。为什么全球和参考?

时间:2015-10-26 19:27:47

标签: c++ templates c++11

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;
}

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

请解释为什么一定是:

  1. 通过引用传递
  2. 全局变量
  3. 提前致谢。

2 个答案:

答案 0 :(得分:2)

模板的指针和引用参数旨在允许您编写仅在它们使用的全局状态方面不同的函数(或类)。

他们消费的状态的位置成为他们的类型(或名称)的一部分,并且必须在编译/链接/加载时确定。

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

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

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

大概double的问题是编译时和运行时双精度和行为可能会有所不同,这会使行为标准化变得棘手。所以,标准只是禁止双重和浮动。

一种常见的技术是用无状态仿函数替换常量。所以你传递了一个“Body functor”而不是Body常量。

仿函数是无状态的,并且const operator()返回Body

答案 1 :(得分:1)

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

您可以使用的其他非类型模板参数是指针和整数类型,例如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);
}