C++ 非类型模板参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5687540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:40:11  来源:igfitidea点击:

Non-type template parameters

c++templates

提问by Mahesh

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'.
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::stringas in the above snippet ?

我明白什么是常数积分表达式。不允许像std::string上面的代码片段那样使用非常量类型的原因是什么?

回答by Xeo

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:

  • 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.

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

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

回答by Nawaz

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

回答by Johannes Schaub - litb

You need to be able to mangle template arguments

您需要能够处理模板参数

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

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

Now an impl would need to come up with a unique sequence of characters for a std::stringor, for that matter, any other arbitrary user defined class, storing a particular value, the meaning of which is not known to the implementation. And in addition, the value of arbitrary class objects can't be calculated at compile time.

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

It's planned to consider allowing literal class types as template parameter types for post-C++0x, which are initialized by constant expressions. 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.

计划考虑允许文字类类型作为 post-C++0x 的模板参数类型,由常量表达式初始化。这些可以通过让数据成员根据它们的值递归地重整来重整(例如,对于基类,我们可以应用深度优先,从左到右遍历)。但这绝对不适用于任意类。

回答by Sadique

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.

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