C++ 的要求是什么? 模板参数?

发布于 2024-07-15 23:07:04 字数 334 浏览 9 评论 0原文

如果您在 C++ 中使用采用整数值作为参数的模板,则对用作参数的整数变量是否有与在函数调用中用作参数时不同的要求?

这是此处问题的后续 . 我特别想解决函数或模板声明为“extern const int”的 WRT 变量是否存在差异?

我可以看到,对于某些模板情况,在编译时需要参数值。 这总是正确的吗? 有没有一种方法可以指定(也许仅针对参数值的某些用途)在运行时使用该值?

If you are using a template in C++ that takes an integer value as a parameter, are there any requirements on an integer variable used as the parameter that are different than if the variable was used as a parameter in a function call?

This is a follow-up to question here . I specifically want to address if there is a difference WRT variables declared as "extern const int" for functions or templates?

I can see that for some template cases the parameter value would be needed at compile time. Is this always true? Is there a way to specify, maybe for only certain uses of the parameter value, that the value be used at runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

茶花眉 2024-07-22 23:07:04

以下内容来自标准。

14.3.2.1:

非类型、非模板模板参数的模板参数应为以下之一:

  • 整型或枚举类型的整型常量表达式; 或
  • 非类型模板参数的名称; 或
  • 具有外部链接的对象或函数的地址,包括函数模板和函数模板ID,但不包括非静态类成员,表示为& id-表达式,其中 & 如果名称引用函数或数组,或者相应的模板参数是引用,则为可选; 或
  • 指向成员的指针,如 5.3.1 中所述表示。

5.19.1:

在一些地方,C++ 需要计算结果为整数或枚举常量的表达式:作为数组边界 (8.3.4, 5.3.4)、作为 case 表达式 (6.4.2)、作为位字段长度 (9.6)、作为枚举器初始值设定项 (7.2)、作为静态成员初始值设定项 (9.4.2) 以及作为整型或枚举非类型模板参数 (14.3)。

 常量表达式: 
              条件表达式 
  

整型常量表达式只能涉及用常量表达式 (8.5) 初始化的整型或枚举类型的文字 (2.13)、枚举数、const 变量或静态数据成员、整型或枚举类型的非类型模板参数以及 sizeof表达式。 浮点文字 (2.13.3) 仅在转换为整型或枚举类型时才会出现。 仅将类型转换为整数或枚举 -
可以使用化类型。 特别是,除了 sizeof 表达式之外,不得使用函数、类对象、指针或引用,并且不得使用赋值、递增、递减、函数调用或逗号运算符。

关于您之前的帖子,我相信“const 变量...初始化与...”部分的本质(我认为外部初始化并不重要)。

The following is from the standard.

14.3.2.1:

A template-argument for a non-type, non-template template-parameter shall be one of:

  • an integral constant-expression of integral or enumeration type; or
  • the name of a non-type template-parameter; or
  • the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
  • a pointer to member expressed as described in 5.3.1 .

5.19.1:

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

 constant-expression:
            conditional-expression

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumera-
tion types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

With respect to your previous post I believe the essence in the part "const variables ... initialised with ..." (and I don't think initialised externally counts).

秋叶绚丽 2024-07-22 23:07:04

它必须是一个整型常量表达式。 5.19 的标准文档对此进行了解释:

整型常量表达式只能涉及用常量表达式 (8.5) 初始化的整型或枚举类型的文字 (2.13)、枚举数、const 变量或静态数据成员、整型或枚举类型的非类型模板参数以及 sizeof表达式。 浮点文字 (2.13.3) 仅在转换为整型或枚举类型时才会出现。 只能使用到整型或枚举类型的类型转换。

请注意,“积分”是“整数”的另一个术语,但与“int”不同。 例如,“char”具有整数/整数类型,但显然不是 int 类型。 具体来说,以下内容是允许的

  • 10 或 10L 或类似的值
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • 当然,上面详述的任何其他模板参数中

的任何一个都可以用作具有相应类型的整型类型的参数的模板参数。 但仍然应用一些转换。 因此,如果它需要一个 int 并且您传递一个 char,它会自动将 char 提升为 int。 如果您提供一个枚举器并且它需要一个 int,则相同。

因此,根据这些规则,如果您有

extern const int SomeName;

And 它没有看到使用整型常量表达式初始化该常量的定义,则它不能用作模板参数。 但当然,它可以用作函数参数。 这些不需要在编译时知道,因为它们不是类型的一部分。 当您命名模板特化时,您使用的参数就成为类型的一部分:

MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!

请注意,还有其他方法可以将 SomeName 作为参数传递。 然而,所有这些都不能被整数模板参数接受。 您可以通过引用参数接受上面的内容,例如

template<const int& V> struct NowItWorks { };

它会接受上面的 SomeName 。 现在,选择的不是一个值,而是整个程序中唯一的特定位置(因为变量具有 extern 链接)。

It has to be a integral constant expression. That's explained by the Standard document at 5.19:

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used.

Note that "integral" is another term for "integer", but is not the same as "int". "char" for example has integer/integral type, but is not the int type, obviously. So concretely, the following is allowed

  • 10 or 10L or anything like that
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • of course, any other template parameter as detailed above

Any of those can be used as a template argument for a parameter that has an integral type of the corresponding type. Some conversions are still applied though. So if it wants an int and you pass a char, it automatically promotes the char to the int. Same if you provide an enumerator and it wants an int.

So by those rules, if you have

extern const int SomeName;

And it does not see a definition which initializes that constant with a integral constant expression, it can't be used as a template argument. But it can be used as a function argument, of course. Those don't need to be known at compile time because those are not part of a type. The moment you name a template specialization, the arguments you used become part of the type:

MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!

Note that there are other ways to pass SomeName as an argument. However, all of which can not be accepted by an integer template parameter. You can accept the above by a reference parameter, for example

template<const int& V> struct NowItWorks { };

And it would accept the SomeName of above. Now, rather than a value, a particular location that is unique across the whole program (as the variable has extern linkage) has been chosen.

执笔绘流年 2024-07-22 23:07:04

编译时总是需要 int 的值。

由于每个模板实例化都是一段单独的编译代码(即使对于整数模板参数也是如此),因此整数在编译时需要可用(并且必须保证永远不会更改)。

这也是为什么当您要使用大量唯一值时最好不要使用整数模板参数 - 您很快就会得到一个巨大的可执行文件。

It is always the case that the value of the int is needed at compile time.

Since each template instantiation is a separate piece of compiled code (even for integer template paramaters) that integer needs to be available when compiled (and it must be guaranteed to never change).

This is also why it's a good idea to not use integer template parameters when you are going to be using a large number of unique values - you can quickly end up with a huge executable file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文