std::transform
,从C++20开始,被声明为constexpr.
我有一堆字符串实用函数,它们接受std::string
参数,但很多用法最终只是传入小的,短的,字符文字序列。我想我应该利用这个事实,声明constexpr
版本,并使用std::string_view
s,而不是创建临时的std::string
变量,只是为了扔掉它们。..
原始STD::STRING
版本:
[[nodiscard]] std::string ToUpperCase(std::string string) noexcept {
std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return string;
}
新STD::STRING_VIEW
版本:
[[nodiscard]] constexpr std::string_view ToUpperCase(std::string_view stringview) noexcept {
std::transform(stringview.begin(), stringview.end(), stringview.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return stringview;
}
但MSVC抱怨道:
error C3892: '_UDest': you cannot assign to a variable that is const
有没有一种方法可以用std::string_view
调用std::transform
,然后把它放回std::string_view
,或者我必须创建一个本地字符串并返回它,从而破坏了最初使用std::string_view
的目的?
[[nodiscard]] constexpr std::string ToUpperCase(std::string_view stringview) noexcept {
std::string copy{stringview};
std::transform(stringview.begin(), stringview.end(), copy.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return copy;
}
2条答案
按热度按时间hujrc8aj1#
不能就地转换
std::string_view
-如果它是从char *const**
构造的呢?很多用法最终只是在编译时传递小的、短的字符文字序列。
。。。但是可以将字符串字面量提升到类型级别
...并添加一个特殊情况。一般来说,这种攻击可以通过范围/元组多态算法来避免。
因此,要使用针对字符文字序列优化的转换,现在编写
ToUpperCase(str_v<"abc">)
而不是ToUpperCase("abc"sv)
。如果您总是希望string_view
作为输出,请在该重载中返回std::string_view{Str<ConstexprToUpper(cs)...>::value}
。7d7tgy0s2#
正如在一条评论中所说,
span
是一个更好的词汇表类型,因为单个元素可以被修改。我也不会将其设置为nodiscard
,因为即使不分配结果,它也很有用:https://godbolt.org/z/Toz8Y9bj9
有点偏离你最初的目标...我认为这是更优雅的,虽然受到膨胀和丑陋的编译错误。它在提供的情况下具有相同的效果。
我也不喜欢
span
的设计(或者string_view
)(练习:添加概念)
https://godbolt.org/z/e9aWKMerE
我发现自己最近经常使用这个成语。