非类型模板参数

Mah*_*esh 81 c++ templates

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

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

我理解常量积分表达式是什么.不允许非常量类型的原因是什么,如std::string上面的代码片段?

Xeo*_*Xeo 113

你不能这样做的原因是因为在编译时不能解析和替换非常量表达式.它们可能在运行时期间发生变化,这需要在运行时生成新模板,这是不可能的,因为模板是编译时的概念.

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

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

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

  • @ALOToverflow:属于"指向成员的指针".它是"指向成员函数的指针"或"指向成员数据的指针". (6认同)
  • 值得注意的是,对于指向对象(或实例字段)的指针,对象必须具有静态存储持续时间和链接(外部预C++ 11,C++ 11中的内部或外部),因此指向它们的指针可以在编译时创建. (3认同)
  • 在C ++ 20中,现在可以允许这种情况,只要该类型具有强的结构相等性,为文字,没有可变/易变的子对象且航天器运算符是公共的即可。 (2认同)

Naw*_*waz 69

这是不允许的.

但是,这是允许的:

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

template <std::string & temp> //reference to object
void g();
Run Code Online (Sandbox Code Playgroud)

参见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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

can assign values locally
can assign values locally
can assign values locally...appended some string
Run Code Online (Sandbox Code Playgroud)

  • @Mahesh:你不知道编译时调用栈是什么样的.在你的函数之前,可能已经被调用了10个或者其他3个或者其他许多,所以创建字符串的堆栈上的地址可以在调用之间改变.当您有一个具有外部链接的对象时,其地址在编译/链接期间是固定的. (11认同)
  • @Mahesh:因为基本上模板的模板是`std :: string`指针或引用对象的地址.如果该变量是本地变量,则每次调用该函数时都可能获得不同的地址. (7认同)
  • 感谢您的参考. (3认同)
  • @Xeo"_its address在编译/ linkage._期间是固定的"或者不是,对于可重定位或位置无关的代码. (2认同)

Joh*_*itb 25

您需要能够破坏模板参数

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

f<"foo">();
f<"bar">(); // different function!?
Run Code Online (Sandbox Code Playgroud)

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

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


Sad*_*que 9

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

常量表达式,具有外部链接的函数或对象的地址,或静态类成员的地址.

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

  • 您使用了引用,那么来源是什么?如果它有引用来源,我想投票。 (2认同)