简体   繁体   English

非类型模板参数

[英]Non-type template parameters

I understand that the non-type template parameter should be a constant integral expression.我知道非类型模板参数应该是一个常量整数表达式。 Can someone shed light why is it so ?有人可以阐明为什么会这样吗?

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

I understand what a constant integral expression is.我明白什么是常数积分表达式。 What are the reasons for not allowing non-constant types like std::string as in the above snippet ?在上面的代码段中不允许像std::string这样的非常量类型的原因是什么?

The reason you can't do this is because non-constant expressions can't be parsed and substituted during compile-time.您不能这样做的原因是因为在编译时无法解析和替换非常量表达式。 They could change during runtime, which would require the generation of a new template during runtime, which isn't possible because templates are a compile-time concept.它们可能会在运行时更改,这将需要在运行时生成新模板,这是不可能的,因为模板是一个编译时概念。

Here's what the standard allows for non-type template parameters (14.1 [temp.param] p4):以下是标准允许的非类型模板参数(14.1 [temp.param] p4):

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:非类型模板参数应具有以下类型之一(可选 cv 限定):

  • integral or enumeration type,整数或枚举类型,
  • pointer to object or pointer to function,指向对象的指针或指向函数的指针,
  • lvalue reference to object or lvalue reference to function,对对象的左值引用或对函数的左值引用,
  • pointer to member,指向成员的指针,
  • std::nullptr_t . std::nullptr_t

That is not allowed.这是不允许的。

However, this is allowed:但是,这是允许的:

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

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

See §14.1/6,7,8 in C++ Standard (2003).请参阅 C++ 标准 (2003) 中的 §14.1/6,7,8。


Illustration:插图:

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

Output:输出:

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

You need to be able to mangle template arguments您需要能够处理模板参数

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

f<"foo">();
f<"foo">(); // same function?

Now an impl would need to come up with a unique sequence of characters for a std::string or, for that matter, any other arbitrary user defined class, storing a particular value, the meaning of which is not known to the implementation.现在,一个 impl 需要为std::string或者任何其他任意用户定义的类提供一个唯一的字符序列,存储一个特定的值,其含义对于实现来说是未知的。 And in addition, the value of arbitrary class objects can't be calculated at compile time.此外,在编译时无法计算任意类对象的值。

It's planned to consider allowing literal class types as template parameter types for post-C++0x (see below), which are initialized by constant expressions.计划考虑允许文字类类型作为 post-C++0x(见下文)的模板参数类型,由常量表达式初始化。 Those could be mangled by having the data members recursively mangled according to their values (for base classes, for example we can apply depth-first, left-to-right traversal).这些可以通过让数据成员根据它们的值递归地重整来重整(例如,对于基类,我们可以应用深度优先,从左到右遍历)。 But it's definitely not going to work for arbitrary classes.但这绝对不适用于任意类。


As of C++20 , we are now allowed to use structural class types as template parameters.C++20 开始,我们现在可以使用结构类类型作为模板参数。 In a nutshell, structural classes must have a constexpr constructor, destructor and only structural-type members and base classes (like scalars, arrays thereof or references).简而言之,结构类必须具有constexpr构造函数、析构函数和只有结构类型成员和基类(如标量、其数组或引用)。 They must also only have public and non- mutable base classes and members.它们还必须只有公共和非mutable基类和成员。 These provisions, if the template is instantiated with a constant expression converted to the parameter type, allow the compiler to mangle the argument meaningfully.这些规定,如果使用转换为参数类型的常量表达式实例化模板,则允许编译器有意义地修改参数。

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time.模板参数列表中提供的非类型模板参数是一个表达式,其值可以在编译时确定。 Such arguments must be:这些参数必须是:

constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.常量表达式、具有外部链接的函数或对象的地址,或静态类成员的地址。

Also, string literals are objects with internal linkage, so you can't use them as template arguments.此外,字符串文字是具有内部链接的对象,因此您不能将它们用作模板参数。 You cannot use a global pointer, either.您也不能使用全局指针。 Floating-point literals are not allowed, given the obvious possibility of rounding-off errors.考虑到四舍五入错误的明显可能性,不允许使用浮点文字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM