【问题标题】:Template Non-Type argument, C++11, restriction for string literals模板非类型参数,C++11,字符串文字的限制
【发布时间】:2015-04-30 01:39:27
【问题描述】:

模板非类型参数的限制规则说:

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

——对于整数或枚举类型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或

——非类型模板参数的名称;或

— 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员, 表示(忽略括号)为 & id-expression,但如果名称引用函数或数组,则 & 可以省略,如果相应的模板参数是引用,则应省略;或

— 一个常量表达式,计算结果为空指针值 (4.10);或

— 一个常量表达式,其值为空成员指针值 (4.11);或

——指向成员的指针,如 5.3.1 所述。

2 [ 注意:字符串文字 (2.14.5) 不满足任何这些类别的要求,因此不是可接受的模板参数。

[ Example:
template<class T, const char* p> class X {
/ ... /
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK
—end example ] —end note ]

那么为什么字符串文字不能用作非类型参数的参数呢?

const char arr[5] = "1234";

arr 与

具有相同的类型 const char[5]
"1234"; 

arr 具有外部链接,这就是为什么在 c++11 标准之前允许使用 arr 作为非类型模板参数的原因。

但是现在指向具有内部链接(静态存储)的对象的指针也允许用作非类型模板参数并且字符串文字具有内部链接。

【问题讨论】:

  • 如果可以扩展语言以允许在调用可变参数 template&lt;char... c&gt; 时使用字符串文字,那就太好了。我想应该很容易做到。它会回避链接问题

标签: c++ templates iso string-literals non-type


【解决方案1】:

从您的问题来看,最接近允许的字符串文字是:

一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象的地址

字符串文字既没有外部链接也没有内部链接,因此不允许使用。

如果您有多个翻译单元,每个翻译单元都包含带有内部链接的 const char arr[5]; 定义,那么这些都是不同的对象,具有不同的地址,但始终位于单个翻译单元 arr == arr 中。实现想出了如何使模板参数工作。

如果您有多个翻译单元,每个都包含"1234",那么这些翻译单元保证有不同的地址。然而,即使在单个翻译单元中,它们也保证具有相同的地址。

如果 "1234" != "1234",那么引用模板 S&lt;"1234"&gt; 没有意义:您每次都会引用不同的模板实例化。

如果是"1234" == "1234",那么实现要确保S&lt;"1234"&gt; 在每个翻译单元中是相同的类型会变得很复杂。

【讨论】:

    【解决方案2】:

    真的很有趣,以下代码是有效的 C++11,但字符串文字不起作用。对于 C++14,您甚至可以删除 static_cast。

    #include <iostream>
    
    static constexpr const char s1[] = "Hello World!";
    static const char s2[] = __DATE__ " " __TIME__;
    
    template< const char* STR > struct X {X() {std::cout << STR << std::endl;}};
    X< s1 > x1;
    X< static_cast<const char*>(s2) > x2;
    
    int main() {}
    

    即使当今的 C++ 编译器不接受字符串文字,在某些情况下允许这样做也会非常方便。

    接受临时类实例化的地址作为 NT 模板参数将朝着类似的方向发展:

    #include <iostream>
    
    struct S {int s;};
    static constexpr const S s1{123};
    static const S s2{999};
    
    template< const S* _S > struct X {X() {std::cout << _S->s << std::endl;}};
    X< &s1 > x1;
    X< &s2 > x2;
    //NOT OK: X< (&S{1}) > x3;
    
    int main() {}
    

    【讨论】:

      猜你喜欢
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 2011-01-03
      相关资源
      最近更新 更多