能够在 C + + 的编译期间创建和操作字符串有几个有用的应用程序。尽管可以在 C + + 中创建编译时字符串,但是这个过程非常繁琐,因为字符串需要声明为一个可变的字符序列,例如。
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
字符串串联、子字符串提取等操作可以很容易地实现为字符序列上的操作。是否可以更方便地声明编译时字符串?如果没有,是否有一个建议允许方便地声明编译时字符串?
理想情况下,我们希望能够像下面这样声明编译时字符串:
// Approach 1
using str1 = sequence<"Hello, world!">;
或者,使用用户定义的文字,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
其中 decltype(str2)
将有一个 constexpr
构造函数。方法1的一个混乱版本可以实现,利用您可以执行以下操作的事实:
template <unsigned Size, const char Array[Size]>
struct foo;
但是,数组需要有外部链接,因此要使方法1工作,我们必须编写如下代码:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
不用说,这很不方便。方法2实际上是不可能实现的。如果我们声明一个(constexpr
)文本操作符,那么我们如何指定返回类型?因为我们需要操作符来返回一个可变的字符序列,所以我们需要使用 const char*
参数来指定返回类型:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
这将导致编译错误,因为 s
不是 constexpr
。试图通过以下方法解决这个问题并没有多大帮助。
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
该标准规定,这个特定的文字运算符形式是为整数和浮点类型保留的。虽然 123_s
会工作,但 abc_s
不会。如果我们完全抛弃用户定义的文字,只使用一个常规的 constexpr
函数会怎么样?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
与前面一样,我们遇到了这样一个问题: 数组(现在是 constexpr
函数的一个参数)本身不再是 constexpr
类型。
我相信应该可以定义一个 C 预处理器宏,它以字符串和字符串的大小作为参数,并返回一个由字符串中的字符组成的序列(使用 BOOST_PP_FOR
、字符串化、数组下标等)。但是,我没有时间(或足够的兴趣)来实现这样的宏 =)