【问题标题】:C++11 Local static values not working as template argumentsC ++ 11本地静态值不能用作模板参数
【发布时间】:2014-11-17 06:37:21
【问题描述】:

在 C++11 中,我似乎无法使用本地静态值作为模板参数。例如:

#include <iostream>
using namespace std;

template <const char* Str>
void print() {
  cout << Str << endl;
}

int main() {
  static constexpr char myStr[] = "Hello";
  print<myStr>();
  return 0;
}

在 GCC 4.9.0 中,代码错误与

error: ‘myStr’ is not a valid template argument of type ‘const char*’ because ‘myStr’ has no linkage

在 Clang 3.4.1 中,代码错误

candidate template ignored: invalid explicitly-specified argument for template parameter 'Str'

两个编译器都使用 -std=c++11 运行

一个在线编译器的链接,您可以在其中选择多种 C++ 编译器之一:http://goo.gl/a2IU3L

注意,将myStr 移到main 之外会按预期编译和运行。

注意,我在 C++11 之前查看过类似的 StackOverflow 问题,大多数都表明这应该在 C++11 中解决。例如Using local classes with STL algorithms

【问题讨论】:

  • 我认为EWG issue 155/N4198 很好地解释了这一点,特别是“对具有链接的实体的限制是导出模板的产物,并且可以在模板类型参数的链接限制时删除被删除”
  • 据我所知,在块范围内声明的变量(在本例中为函数变量)没有链接,除非声明为 extern,在这种情况下,它具有外部链接。我不确定有没有办法用内部链接声明块范围变量。
  • @PiotrS。我不知道 C++ [EWG issue 155/N4198] 指的是哪个版本。是 C++11 的吗?
  • 这是一篇日期为 2014-10-06 的论文;它是对未来语言发展的提议,涉及最新的 C++ 标准对语言施加的限制。换句话说,截至目前,您的myStr 是一个对象的地址,没有无链接(尽管它具有静态存储持续时间),因此标准不允许作为非类型模板参数。建议去除“链接”约束,使具有静态存储持续时间的对象的地址成为允许作为非类型模板参数的常量表达式。
  • Apparently 您的代码示例由更新的编译器(gcc 7.2 或更新版本)和更新的语言方言(C++17 或更新版本)编译。

标签: c++ templates c++11


【解决方案1】:

显然“无链接”意味着"The name can be referred to only from the scope it is in." 包括局部变量。这些在模板参数中无效,因为它们的地址在编译时显然是未知的。

简单的解决方案是将其设为全局变量。它并没有真正改变你的代码。

另见https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52036

【讨论】:

  • 上面的代码是从原始上下文中简化的。在我的实际代码中,我有一个创建两行的宏:const 字符串和函数调用。宏不能创建全局变量和局部函数调用。
  • 关于 gcc 错误,知道为什么 clang 会以同样的方式失败吗?
  • @user108088 clang 中的相同错误?
  • @user108088。我认为这个 gcc 错误是 staticextern。 Clang 接受内部与外部链接,gcc 看到 static 没有链接。 coliru.stacked-crooked.com/a/2d93fe317886484d
  • @BЈовић 如果这是 gcc 中的一个错误,那么我预计另一个独立生成的编译器不太可能有相同的错误。 Clang 也不编译代码。
猜你喜欢
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多