What would be a good implementation of iota_n (missing algorithm from the STL)

前端 未结 3 946
甜味超标
甜味超标 2020-12-19 02:28

With C++11, the STL has now a std::iota function (see a reference). In contrast to std::fill_n, std::generate_n, there is no std

3条回答
  •  隐瞒了意图╮
    2020-12-19 03:03

    You're so focused on code generation that you forgot to get the interface right.

    You correctly require OutputIterator, but what happens if you want to call it a second time?

    list list(2 * N);
    iota_n(list.begin(), N, 0);
    // umm...
    iota_n(list.begin() + N, N, 0); // doesn't compile!
    iota_n(list.rbegin(), N, 0); // works, but create 0..N,N-1..0, not 0..N,0..N
    auto it = list.begin();
    std::advance(it, N);
    iota_n(it, N, 0); // works, but ... yuck and ... slow (O(N))
    

    inside iota_n, you still know where you are, but you've thrown that information away, so the caller cannot get at it in constant time.

    General principle: don't throw away useful information.

    template 
    auto iota_n(OutputIterator dest, SizeType N, ValueType value) {
        while (N) {
            *dest = value;
            ++dest;
            ++value;
            --N;
        }
        // now, what do we know that the caller might not know?
        // N? No, it's zero.
        // value? Maybe, but it's just his value + his N
        // dest? Definitely. Caller cannot easily compute his dest + his N (O(N))
        //       So, return it:
        return dest;
    }
    

    With this definition, the above example becomes simply:

    list list(2 * N);
    auto it = iota_n(list.begin(), N, 0);
    auto end = iota_n(it, N, 0);
    assert(end == list.end());
    

提交回复
热议问题