【问题标题】:C++ non-type template parameter const char*C++ 非类型模板参数 const char*
【发布时间】:2015-07-19 18:22:53
【问题描述】:

假设我们有

template <const char*>
struct A{};

// static storage
const char a[] = "asd";
const char* p = "asd";

这个实例化

A<a>{};

对编译器来说没问题。这是可以理解的——数组a 衰减为指向第一个元素的指针。但是如果我们像这样用p 实例化A

A<p>{};

编译器报错:

错误:'char *' 类型的非类型模板参数不是常量表达式

为什么标准不允许指定类型为const char* 的命名变量或仅指定字符串文字"asd",即btw lvalue 本身,作为模板参数?

【问题讨论】:

  • 我不相信它与左值有关,因为 p 没有精确的内存位置,但 a 有。
  • 这和template &lt;int&gt; struct X{}; int p = 5; X&lt;p&gt; x;没有区别

标签: c++ templates


【解决方案1】:

数组a 是一个字符常量数组,它在编译时被完全初始化,并且编译器也得到一个已知的内存地址,这就是它可以衰减到模板中的指针的原因。

但是p是一个指针指向一个常量字符数组,但是指针本身不是编译时常量,可以改成指向其他字符串,它是不是在编译时初始化,而是在链接时(编译后发生)或程序加载到内存时初始化。 p 的地址在编译时是已知的,但不是字符串文字 p 指向的地址。


为了解释在编译时不知道字符串文字地址的原因,这是因为编译器代码生成器将它放在一个特殊的只读段中,然后将该只读段与链接时来自其他translation units 的只读段。这就是为什么要到链接时(最早)才能知道字符串文字的最终地址。

【讨论】:

  • 谢谢,有道理。但是为什么即使我使用它也不起作用 constexpr const char* p = "something"; ?
  • @Bikineev 确实是同样的问题,在编译时无法计算字符串文字的位置,而模板需要它。
  • 非常感谢!很好的答案
【解决方案2】:

如果您想象p 被某个函数初始化,这可能有助于更多地理解为什么不允许使用A&lt;p&gt;{};

const char* p = getP();

getP() 通过一些运行时数据确定其结果,例如,通过读取配置文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-02
    • 2022-01-16
    • 1970-01-01
    • 2020-01-20
    • 2014-10-03
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    相关资源
    最近更新 更多