C++11中的原始字符串字面量非常好,除了格式化它们的明显方式导致第一个字符是冗余的换行符\n
。
请看这个例子:
some_code();
std::string text = R"(
This is the first line.
This is the second line.
This is the third line.
)";
more_code();
显而易见的变通方案看起来非常丑陋:
some_code();
std::string text = R"(This is the first line.
This is the second line.
This is the third line.
)";
more_code();
有没有人找到一个优雅的解决方案呢?
8条答案
按热度按时间u1ehiz5o1#
通过在字符串文本自动转换为的
const char*
上加1,可以获得指向第二个字符的指针(跳过前导换行符):恕我直言,上面的代码在中断周围代码的缩进方面存在缺陷。一些语言提供了一个内置函数或库函数,可以做如下操作:
它允许以下用法:
编写这样的函数相对简单...
(The一个有点奇怪的
p_leading[i]
方法旨在让使用制表符和空格的人的生活不会比他们自己的生活更困难;-P,只要行以相同的顺序开始。)31moq8wy2#
这可能不是您想要的,但为了以防万一,您应该注意自动字符串文字连接:
yks3o0rb3#
我推荐@Brian 's answer,特别是如果你只需要几行文字,或者你可以用你的文字编辑器来处理的话。如果不是这样的话,我有一个替代方案。
Live example
原始字符串常量仍然可以与“普通”字符串常量连接,如代码所示,开头的
"\
意味着从第一行“消除”"
字符,将其放在自己的行中。不过,如果我决定的话,我还是会把这些文本放到一个单独的文件中,然后在运行时加载它。不过这对你来说没有压力:-)。
而且,这也是我最近写的比较难看的代码之一。
prdp8dxp4#
我能看到的最接近的是:
如果在分隔符序列中允许使用空格,那就更好了。
我的预处理器会给你一个警告,但不幸的是,它有点没用。Clang和GCC完全被抛弃了。
nszi6y055#
接受的答案会从
clang-tidy
产生警告cppcoreguidelines-pro-bounds-constant-array-index。请参见Pro.bounds:有关详细信息,请参见边界安全性配置文件。如果您没有
std::span
,但至少使用C++17编译,请考虑:其主要优点是可读性(恕我直言),并且您可以在代码的其余部分打开这个整齐的警告。
使用
gcc
时,如果有人无意中将原始字符串简化为空字符串,则会出现编译器错误(demo),而可接受的方法要么不产生任何结果(demo),要么根据编译器设置出现“outside bounds of constant string”警告。ecfdbz9o6#
我也遇到了同样的问题,我认为下面的解决方案是以上所有解决方案中最好的。我希望它对你也有帮助(见评论中的例子):
tp5buhyn7#
是的,这很烦人。也许应该有原始文本(
R"PREFIX("
)和 * multiline * 原始文本(M"PREFIX
)。我想出了这个替代方案,几乎描述自己:
局限性:
1.如果原始文本为空,它将生成一个无效字符串,但这应该是显而易见的。
1.如果原始文本没有以新行开始,它将替代第一个字符。
std::next
仅在C++17中是constexpr
,然后您可以使用1+(char const*)R"XYZ("
,但它不太清楚,可能会产生警告。此外,没有担保;)。毕竟,我不知道用指向静态数据的指针进行算术运算是否合法。
+ 1
方法的另一个优点是它可以放在最后:可能性是无限的:
一个三个三个一个
qzlgjiam8#
在C++20中,这可以通过使用字符串字面运算符模板在编译时完全实现。
这有几个主要好处:
const char (&)[N]
)的引用-类似于C++中的普通字符常量;所以没有std::array
恶作剧和生命周期问题。用法示例:godbolt
通常情况下,不可能将字符串常量作为模板参数传递,例如:
但是在C++20中,我们现在可以有类类型的模板参数,并且这些参数可以从字符串常量初始化。
与新的字符串文字运算符模板结合使用,可以将整个字符串文字作为模板参数获取:
将长度和单个字符都作为常量表达式,使我们能够在编译时计算未缩进字符串所需的长度,并将结果字符串存储在另一个模板参数中(这样我们只需要返回对最终字符串值的引用):
完整代码:godbolt