模板指针参数包

时间:2018-02-12 18:23:32

标签: c++ templates language-lawyer variadic-templates

为什么带有模板参数包指针的模板函数无法使用相同指针的偏移量进行实例化?

我的意思是:鉴于这个简短的代码,为什么我必须注释掉最后两行?

template <int * ... pt> void f() {}

int n[] = {1, 2, 3};
int m = n[1];

int main()
{
    f<n>();  // this is accepted
    f<n, &m>();  // this is accepted too
    //f<n, n+1>(); // this is not.
    //f<n, &n[1]>(); // this isn't accepted neither
}

n+1代表与&m相同的地址吗?或者链接有什么不同?还有什么?

2 个答案:

答案 0 :(得分:3)

请参阅cppreference.com - Template non-type arguments

  
      
  • 对于指向对象的指针,模板参数必须指定具有静态存储持续时间和链接(内部或外部)的对象的地址,或者指定为适当的空指针或std :: nullptr_t值的常量表达式
  •   
     

...

     

唯一的例外是引用和指针类型的非类型模板参数不能引用/是

的地址      
      
  • 子对象(包括非静态类成员,基础子对象或数组元素);
  •   
  • 临时对象(包括在引用初始化期间创建的对象);
  •   

因此不允许使用数组元素的地址。

答案 1 :(得分:2)

在C ++ 17中,来自[temp.arg.nontype]

  

对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或者对于指针类型,不应该是地址):

     
      
  • 一个子对象,
  •   
  • [...]
  •   

子对象的位置,来自[intro.object]

  

对象可以包含其他对象,称为子对象。子对象可以是成员子对象([class.mem]),基类子对象([class.derived])或数组元素。

使用&m作为非类型模板参数很好 - 它指向一个对象。该对象恰好是从n[1]初始化的,但这并不重要。

另一方面,n+1&n[1]都指向数组n的元素,也就是说它们都指向n的子对象,因此这是不允许的。 n+1&m无关。

C++11C++14中,措辞是包含而非独占,但结论是相同的:

  

非类型非模板模板参数 template-argument 应为以下之一:

     
      
  • [...]
  •   
  • 一个常量表达式([expr.const]),用于指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或具有外部或内部链接的函数,包括函数模板和function template-ids但不包括非静态类成员,表示(忽略括号)为[...]
  •   
  • [...]
  •   

允许指向m的指针,指向n[1]的指针不允许。