How to filter a std::integer_sequence

前端 未结 3 1707
一个人的身影
一个人的身影 2021-01-06 01:49

If I theoretically have a sequence of integers like

std::integer_sequence

How can I filter it with

3条回答
  •  长发绾君心
    2021-01-06 02:16

    Filtering a sequence is equivalent to transforming a sequence of values into a sequence of sequences of at most one value and then concatenating them. That is, filtering the even values from <0,1,2,3> would be the same as transforming that into the sequence <<0>,<>,<2>,<>> and concatenating to yield <0,2>.

    With C++17, this takes remarkably little code. We'll start with our own value and sequence type (you can easily convert a std::integer_sequence to a value_sequence):

    template 
    struct value { };
    
    template 
    struct value_sequence { };
    

    The reason we use our own is so we can add operators to it. Like +:

    template 
    constexpr value_sequence operator+(value_sequence,
                                                     value_sequence )
    {
        return {};
    }
    

    We'll use that for concatenation. Next, we add a function to transform a single value into a sequence of zero or one element:

    template 
    constexpr auto filter_single(value, F predicate) {
        if constexpr (predicate(Val)) {
            return value_sequence{};
        }
        else {
            return value_sequence<>{};
        }
    }
    

    And lastly, we just need our top-level filter to put it all together:

    template 
    constexpr auto filter(value_sequence, F predicate) {
        return (filter_single(value{}, predicate) + ...);
    }
    

    Usage from the original example:

    constexpr auto evens = filter(
        value_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9>{},
        [](int i) constexpr { return i%2 == 0; });
    

    How cool is C++17!

提交回复
热议问题