字符串文本不能有外部链接的原因是什么?

Is there a reason string literals can't have external linkage?

本文关键字:是什么 链接 文本 不能 外部 字符串      更新时间:2023-10-16

想要带有外部链接的字符串文字的主要动机是使用字符串文字作为非类型模板参数。

我会想象一个带有外部链接的字符串文字,其定义类似于

前缀中包含 e 的字符串文本是具有外部链接的字符串文本

template<auto&> struct S{};
void bar()
{
S<e"foo"> s;
}

将具有等同于

template<auto&> struct S{};
constexpr char __foo[] = "foo";
void bar
{
S<__foo> s;
}

是否有理由不使用外部链接字符串文字? 以某种方式添加另一个前缀(如e"Lorem Ipsum")以使字符串文字对外部链接有害吗?

注意:已经可以实现外部链接字符串,但这是一种可怕的做事方式。

#include<boost/metaparse/v1/string.hpp>
template<typename>
struct hack;
template<char... Cs>
struct hack<boost::metaparse::v1::string<Cs...>>
{
static constexpr char arr[] = {Cs..., ''};
};
#define E(str) hack<BOOST_METAPARSE_STRING(str)>::arr
template<auto&> struct S{};
S<E("I'm an external linkage string")> s;  // compiles

Boost使用python脚本来生成BOOST_METAPARSE_STRING的实现,这很糟糕。

由于非类型模板参数中的 P0732 类类型,这个问题将在 C++20 中变得毫无意义。

非类型模板参数是基本类型和类类型之间不对称的最后痕迹。它的存在不是出于选择,而是出于必要:不清楚链接者应该如何处理它们。

链接器需要能够区分两个模板类,为此,它需要回答两个对象(ab是否相等。对于基本类型来说,这是微不足道的,但对于使用 C++20 之前可用的工具的类类型是无法解决的。

P0515一致性比较给出了确定两个类类型对象是否相等的机制,前提是它们具有琐碎的operator<=>,具有成员比较的语义。

如果 P0732 通过,您将能够写

template<size_t N>
struct fixed_string
{
constexpr fixed_string(const char (&str)[N]) { std::copy(str, str + N, data); }
auto operator<=>(const fixed_string&, const fixed_string&) = default;
char data[N];
};
template<size_t N>
fixed_string(const char(&)[N]) -> fixed_string<N>;
template<fixed_string> struct S {};
S<"foo"> s;

另请参阅有关文本格式库的想法,该库也倾向于进入 C++20。

只能使用 constexpr 函数解析字符串。 下面是一个非常简单的示例:

constexpr int placeholder_count(const char* s, size_t i = 0, int result = 0)
{
return s[i] == 0
? result
: (s[i] == '%')
? placeholder_count(s, i + 1, result + 1)
: placeholder_count(s, i + 1, result);
}
int main()
{
static_assert(placeholder_count("foo %s bar %d") == 2, "");
return 0;
}

https://wandbox.org/permlink/TwN0UALpp0e6qfqr

你可以使用它实现很多实用的东西,特别是如果允许C++14,那么需要的递归就少得多。

对于更高级的用例,请查看元解析: http://www.boost.org/doc/libs/1_64_0/doc/html/metaparse.html

§ 3.5 程序和链接 [basic.link]

  1. 名称可能表示与由另一个作用域中的声明引入的名称

如评论中所述,只有名称才有联系。字符串文本不是名称。

§ 2.13.5 字符串文字 [lex.string]

    计算字符串文字
  1. 会导致具有静态存储持续时间的字符串文字对象,从给定字符初始化为 上面指定。是否所有字符串文本都是不同的(即, 存储在非重叠对象中)以及是否连续 字符串文本的计算产生相同或不同的对象 未指定

所以实际问题是具有相等值的不同字符串文字可以存储在不同的对象中。更重要的是,对同一文本的连续计算可以产生不同的对象。