c++ - 字符串文字不允许作为非类型模板参数

标签 c++ templates string-literals

以下引用来自 Addison Wesley 的 C++ 模板。有人可以用简单的英语/外行术语帮助我理解它的要点吗?

Because string literals are objects with internal linkage (two string literals with the same value but in different modules are different objects), you can't use them as template arguments either:

最佳答案

您的编译器最终会在名为 translation units, informally called source files 的东西上运行。 .在这些翻译单元中,您可以识别不同的实体:对象、函数等。链接器的工作是将这些单元连接在一起,而该过程的一部分是合并身份。

标识符有链接:内部链接表示该翻译单元中命名的实体仅对该翻译单元可见,而< em>external links 表示实体对其他单位可见。

当一个实体被标记为static时,它被赋予internal链接。所以给定这两个翻译单元:

// a.cpp
static void foo() { /* in a */ } 

// b.cpp
static void foo() { /* in a */ } 

每个 foo 都引用一个实体(在这种情况下是一个函数),该实体仅对其各自的翻译单元可见;也就是说,每个翻译单元都有自己的foo

这里有一个问题:字符串字面量与 static const char[..] 的类型相同。那就是:

// str.cpp
#include <iostream>

// this code:

void bar()
{
    std::cout << "abc" << std::endl;
}

// is conceptually equivalent to:

static const char[4] __literal0 = {'a', 'b', 'c', 0};

void bar()
{
    std::cout << __literal0 << std::endl;
}

如您所见,文字的值在该翻译单元内部。因此,例如,如果您在多个翻译单元中使用 "abc",它们最终都会成为不同的实体。

总的来说,这意味着这在概念上毫无意义:

template <const char* String>
struct baz {};

typedef baz<"abc"> incoherent;

因为 "abc" 对于每个翻译单元不同。每个翻译单元都会被赋予一个 不同的 类,因为每个 "abc" 都是不同的实体,即使它们提供了“相同”的参数。

在语言层面,这是通过说模板非类型参数可以是指向具有外部链接的实体的指针;也就是说,的事情在翻译单元中引用同一个实体。

所以这很好:

// good.hpp
extern const char* my_string;

// good.cpp
const char* my_string = "any string";

// anything.cpp
typedef baz<my_string> coherent; // okay; all instantiations use the same entity

†并非所有标识符都有链接;有些没有,比如函数参数。

‡ 优化编译器会将相同的文字存储在同一地址,以节省空间;但这是实现细节的质量,而不是保证。

关于c++ - 字符串文字不允许作为非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5547852/

相关文章:

python -\newline 转义序列在 python 中是什么意思?

c++ - 在模板函数包装器中处理 void 返回

c++ - 检查两种类型是否具有可比性

c++ - 对类方法进行指针部分特化时获取 "illegal use of explicit template arguments"

c++ - 在不向用户公开库的情况下静态包装库的多态迭代器

postgresql - Postgres 字符串前的 "E"是什么?

c - 为什么在 Linux 上字符串文字的内存地址与其他的如此不同?

c++ - 包装一行预处理器 C++

c++ - 指针在删除它并在 C++ 中再次分配新内存后是否获得相同的内存地址?

c++ - 为什么 GMOCK 对象不返回依赖注入(inject)中 EXPECT_CALL 设置的值