Aqu*_*irl 37 c++ templates string-literals
以下引用来自Addison Wesley的C++模板.有人可以帮助我用简单的英语/外行人的术语来理解它的要点吗?
因为字符串文字是具有内部链接的对象(两个字符串文字具有相同的值但在不同的模块中是不同的对象),所以您不能将它们用作模板参数:
GMa*_*ckG 47
您的编译器最终运行在称为翻译单元的东西上,非正式地称为源文件.在这些翻译单元中,您可以识别不同的实体:对象,函数等.链接器作业是将这些单元连接在一起,并且该过程的一部分是合并标识.
标识符有联动†:内部链接是指在翻译单元命名的实体是只对翻译单元可见,而外部链接意味着该实体是给其他单位可见.
标记实体时static,会给出内部链接.所以考虑到这两个翻译单元:
// a.cpp
static void foo() { /* in a */ }
// b.cpp
static void foo() { /* in a */ }
Run Code Online (Sandbox Code Playgroud)
这些中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;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,文字的值是该翻译单元的内部值.因此,如果您"abc"在多个翻译单元中使用,例如,它们最终都是不同的实体.‡
总的来说,这意味着这在概念上毫无意义:
template <const char* String>
struct baz {};
typedef baz<"abc"> incoherent;
Run Code Online (Sandbox Code Playgroud)
因为每个翻译单元"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
Run Code Online (Sandbox Code Playgroud)
†并非所有标识符都具有链接; 有些没有,比如功能参数.
‡优化编译器将相同的文字存储在同一地址,以节省空间; 但这是一个实施细节的质量,而不是保证.
Ton*_*roy 11
这意味着你不能这样做......
#include <iostream>
template <const char* P>
void f() { std::cout << P << '\n'; }
int main()
{
f<"hello there">();
}
Run Code Online (Sandbox Code Playgroud)
...因为"hello there"并非100%保证解析为可用于实例化模板的单个整数值(尽管大多数好的链接器将尝试折叠链接对象的所有用法并生成具有单个副本的新对象字符串).
但是,您可以使用外部字符数组/指针:
...
extern const char p[];
const char p[] = "hello";
...
f<p>();
...
Run Code Online (Sandbox Code Playgroud)
显然,像"foobar"这样的字符串文字与其他文字内置类型(如int或float)不同.他们需要一个地址(const char*).地址实际上是编译器替换文字出现位置的常量值.该地址指向某个地方,在编译时修复,在程序的内存中.
因此,它必须是内部联系.内部链接仅意味着不能跨翻译单元(已编译的cpp文件)进行链接.编译器可以尝试这样做,但不是必需的.换句话说,内部链接意味着如果你在不同的cpp文件中获取两个相同的文字字符串的地址(即它们转换为的const char*的值),它们通常不会相同.
您不能将它们用作模板参数,因为它们需要strcmp()来检查它们是否相同.如果您使用了==,那么您只需要比较地址,当模板在不同的翻译单元中使用相同的文字字符串进行实例化时,这些地址就不一样了.
其他更简单的内置类型,如文字,也是内部链接(它们没有标识符,不能从不同的翻译单元链接在一起).然而,他们的比较是微不足道的,因为它是有价值的.所以它们可以用于模板.
| 归档时间: |
|
| 查看次数: |
5784 次 |
| 最近记录: |