【问题标题】:What are the requirements for C++ template parameters?C++模板参数有什么要求?
【发布时间】:2010-10-13 05:26:39
【问题描述】:

如果您在 C++ 中使用一个将整数值作为参数的模板,那么对于用作参数的整数变量是否有任何不同于将变量用作函数调用中的参数的要求?

这是对问题 here 的跟进。我特别想解决函数或模板中声明为“extern const int”的 WRT 变量是否存在差异?

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

【问题讨论】:

    标签: c++ templates parameters constants extern


    【解决方案1】:

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

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

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

    • 10 or 10L or anything like that
    • enum { THIS, OR, THAT };
    • int const this_one = 10;
    • sizeof(char)
    • 当然,上面详述的任何其他模板参数

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

    所以根据这些规则,如果你有

    extern const int SomeName;
    

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

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

    请注意,还有其他方法可以将SomeName 作为参数传递。但是,整数模板参数可以接受所有这些。您可以通过引用参数接受上述内容,例如

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

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

    【讨论】:

      【解决方案2】:

      以下内容来自标准。

      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)。

       constant-expression:
                  conditional-expression
      

      一个整型常量表达式只能包含字面量 (2.13)、枚举器、常量变量或整型或枚举类型的静态数据成员,这些类型使用常量表达式 (8.5)、整型或枚举类型的非类型模板参数和 sizeof表达式。浮动文字 (2.13.3) 只有在转换为整数或枚举类型时才能出现。仅类型转换为整数或枚举 化类型可以使用。特别是,除了 sizeof 表达式,不得使用函数、类对象、指针或引用,不得使用赋值、递增、递减、函数调用或逗号运算符。

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

      【讨论】:

        【解决方案3】:

        在编译时总是需要 int 的值。

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-12
          • 1970-01-01
          • 2015-05-13
          相关资源
          最近更新 更多