给定str
的是一个字符串
auto str = std::string{};
getline(std::cin, str);
我注意到当我们view::filter
在惰性范围内存在时,即使使用 -O3,也会有许多冗余的哨兵检查。CE godbolt.org/g/B3ZGbm
for (auto sv : str | ranges::view::delimit('#')
// (1) pointer check and delimit check here
| ranges::view::filter(onlyalpha)
// (2) pointer check and delimit check here also!
| ranges::view::transform(to_ints) ) {
std::cout << sv;
// (3) pointer check and delimit check here too!
}
但是,如果我尝试像这样将该过滤器嵌入到变换中
auto to_ints_with_filter = [](unsigned char ch){
if (std::isalpha(ch)) {
auto index = (ch - 1) & 0b0001'1111;
static constexpr auto table =
std::array<char,27> {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
};
return std::string_view(&table[index],1);
}
else
return std::string_view();
};
多余的哨兵检查都没有了。CE godbolt.org/g/4sMYhM
for (auto sv : str | ranges::view::delimit('#')
| ranges::view::transform(to_ints_with_filter ) ) {
std::cout << sv;
}
为什么优化器在存在时不能摆脱那些冗余检查view::filter
?
这是否被认为是微不足道的开销view::filter
?
更新
std::string_view(nullptr)
按照凯西在评论中的指示更改std::string_view()
为坏。
-DNDEBUG
按照凯西在评论中的指示添加后。循环结束检查现在消失了。在进入转换之前还有额外的检查。CE godbolt.org/g/YWUPaK
for (auto sv : str | ranges::view::delimit('#')
// (1) pointer check and delimit check here
| ranges::view::filter(onlyalpha)
// (2) pointer check and delimit check here also
| ranges::view::transform(to_ints) ) {
std::cout << sv;
}
有了-DNDEBUG
,它的产量要好得多,但似乎还有一个多余的挥之不去。
更新 2
我尝试添加另一个变换。似乎在它本身之后只有一组冗余检查view::filter
。CE godbolt.org/g/sSt8qb
for (auto sv : str | ranges::view::delimit('#')
// (1) pointer check and delimit check here
| ranges::view::filter(onlyalpha)
// (2) pointer check and delimit check here also
| ranges::view::transform(to_ints)
| ranges::view::transform(to_ints2) ) {
std::cout << sv;
}