模板(C ++)中的参数值:可以在运行时指定吗?

时间:2018-05-13 10:49:03

标签: c++ templates

我是C ++的新手,我有一个问题。 让我们说我有一个类,函数定义和一个主要完成(here源代码):

// sequence template
#include <iostream>
using namespace std;

template <class T, int N>
class mysequence {
    T memblock [N];
  public:
    void setmember (int x, T value);
    T getmember (int x);
};

template <class T, int N>
void mysequence<T,N>::setmember (int x, T value) {
  memblock[x]=value;
}

template <class T, int N>
T mysequence<T,N>::getmember (int x) {
  return memblock[x];
}

int main () {
  mysequence <int,5> myints;
  mysequence <double,5> myfloats;
  myints.setmember (0,100);
  myfloats.setmember (3,3.1416);
  cout << myints.getmember(0) << '\n';
  cout << myfloats.getmember(3) << '\n';
  return 0;
}

问题是:在template <class T, int N>中,是否应该在编译时知道值N(就像在这种情况下一样)?或者可以在运行时指定?

1 个答案:

答案 0 :(得分:2)

是。所有模板参数都需要在编译时知道(其他任何事情都会导致编译器错误)。

这样做的原因是从技术上讲,mysequence<int, 1>mysequence<int, 2>是完全独立的类型,由编译器生成。如果编译器以前从未见过您的N,那么它如何为您生成类型?

编译器需要单独生成这些类型的事实也是迫使您实现模板in the header的原因。在运行时确定参数显然会更难做(您需要动态重新编译代码!)。

以下是C ++标准对模板参数(不是类型)的说法:

  

非类型模板参数的模板参数应为模板参数类型的转换常量表达式

[temp.arg.nontype]/2

现在什么是转换的常量表达式

  

T类型的转换常量表达式是一个表达式,隐式转换为类型T,其中转换后的表达式是常量表达式
  [对可能应用的转化的一些限制,请遵循]

[expr.const]/5

实际上,它只是一个常量表达式并添加了一些转换。什么是常量表达式的规则有点复杂([expr.const]/2),但标准有一个简单的总结:

  

假设执行复制省略,满足这些要求的表达式称为常量表达式。    [注意:在翻译期间可以评估常量表达式。 - 尾注]

[expr.const]/1

在翻译期间进行评估是一个奇特的术语,编译器可以在编译时完成。&#34;

因此,必须在编译时知道非类型模板参数(因此,请键入模板参数,尽管构建一个您希望在运行时设置类型模板参数的场景更难)