3

给定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;
}
4

0 回答 0