非类型模板参数

时间:2011-04-16 15:32:05

标签: c++ templates

据我所知,非类型模板参数应该是一个常量整数表达式。有人可以解释为什么会如此?

template <std::string temp>
void foo()
{
     // ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.

我理解常量积分表达式是什么。不允许像上面代码段中的std::string这样的非常量类型的原因是什么?

4 个答案:

答案 0 :(得分:109)

您无法执行此操作的原因是因为在编译时无法解析和替换非常量表达式。它们可能在运行时期间发生变化,这需要在运行时生成新模板,这是不可能的,因为模板是编译时的概念。

这是标准允许非类型模板参数的内容(14.1 [temp.param] p4):

  

非类型模板参数应具有以下(可选的cv限定)类型之一:

     
      
  • 整数或枚举类型,
  •   
  • 指向对象或指向函数的指针,
  •   
  • 对对象的左值引用或对函数的左值引用,
  •   
  • 指向成员的指针,
  •   
  • std::nullptr_t
  •   

答案 1 :(得分:64)

这是不允许的。

然而,这是允许的:

template <std::string * temp> //pointer to object
void f();

template <std::string & temp> //reference to object
void g();

参见C ++ Standard(2003)中的§14.1/ 6,7,8。


插图:

template <std::string * temp> //pointer to object
void f()
{
   cout << *temp << endl;
}

template <std::string & temp> //reference to object
void g()
{
     cout << temp << endl;
     temp += "...appended some string";
}

std::string s; //must not be local as it must have external linkage!

int main() {
        s = "can assign values locally";
        f<&s>();
        g<s>();
        cout << s << endl;
        return 0;
}

输出:

can assign values locally
can assign values locally
can assign values locally...appended some string

答案 2 :(得分:23)

您需要能够破坏模板参数

template <std::string temp>
void f() {
 // ...
}

f<"foo">();
f<"bar">(); // different function!?

现在一个impl需要为std::string提供一个唯一的字符序列,或者就此而言,任何其他任意用户定义的类,存储一个特定的值,其含义是未知的实施。此外,在编译时无法计算任意类对象的值。

计划考虑允许文字类类型作为后C ++ 0x的模板参数类型,它们由常量表达式初始化。这些可能会因数据成员根据其值递归地进行损坏而受到损害(对于基类,例如我们可以应用深度优先,从左到右的遍历)。但它肯定不会适用于任意类。

答案 3 :(得分:8)

模板参数列表中提供的非类型模板参数是一个表达式,其值可以在编译时确定。这些论点必须是:

  

常量表达式,地址   具有外部功能或对象   连接或静态类的地址   成员。

此外,字符串文字是具有内部链接的对象,因此您不能将它们用作模板参数。您也不能使用全局指针。考虑到出现舍入误差的明显可能性,不允许使用浮点文字。