【发布时间】: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 或更新版本)编译。