Cas*_*sey 5 c++ toupper tolower string-view c++20
std::transform从 C++20 开始,声明constexpr.我有一堆带std::string参数的字符串实用函数,但很多用法最终只是在编译时传递小而短的字符文字序列。constexpr我想我会利用这个事实并声明 和take s的版本,std::string_view而不是创建临时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;
}
Run Code Online (Sandbox Code Playgroud)
新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;
}
Run Code Online (Sandbox Code Playgroud)
但 MSVC 抱怨道:
error C3892: '_UDest': you cannot assign to a variable that is const
Run Code Online (Sandbox Code Playgroud)
有没有办法用std::transforma进行调用std::string_view并将其放回到 the 中,std::string_view或者我是否必须创建一个本地字符串并返回它,从而破坏了 using 的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;
}
Run Code Online (Sandbox Code Playgroud)
你不能就地转换 a std::string_view- 如果它是由 构造的怎么办?char const*
许多用法最终只是在编译时传递小而短的字符文字序列。
...但是您可以将字符串文字提升到类型级别
namespace impl {
template<std::size_t n> struct Str {
std::array<char, n> raw{};
constexpr Str(char const (&src)[n + 1]) { std::copy_n(src, n, raw.begin()); }
};
template<std::size_t n> Str(char const (&)[n]) -> Str<n - 1>;
}
template<char... cs> struct Str { static char constexpr value[]{cs..., '\0'}; };
template<impl::Str s>
auto constexpr str_v = []<std::size_t... is>(std::index_sequence<is...>) {
return Str<s.raw[is]...>{};
}(std::make_index_sequence<s.raw.size()>{});
Run Code Online (Sandbox Code Playgroud)
...并添加一个特殊情况。一般来说,可以使用范围/元组多态算法来避免这种黑客攻击。
[[nodiscard]] constexpr auto ToUpperCase(auto str) {
for (auto&& c: str) c = ConstexprToUpper(c); // std::toupper doesn't seem constexpr
return str;
}
template<char... cs> [[nodiscard]] constexpr auto ToUpperCase(Str<cs...>) {
return Str<ConstexprToUpper(cs)...>{};
}
Run Code Online (Sandbox Code Playgroud)
因此,要使用针对字符文字序列优化的转换,现在编写ToUpperCase(str_v<"abc">)而不是ToUpperCase("abc"sv). 如果您总是想要string_view作为输出,请std::string_view{Str<ConstexprToUpper(cs)...>::value}在该重载中返回。