什么是iota_n的良好实现(来自STL的遗漏算法)

Tem*_*Rex 10 c++ algorithm stl iota c++11

使用C++ 11,STL现在具有一个std::iota功能(参见参考资料).然而std::fill_n,与之相反,std::generate_n却没有std::iota_n.什么是一个很好的实现呢?std::generate_n使用简单的lambda表达式(替代2)直接循环(替代1)或委托?

备选方案1)

template<class OutputIterator, class Size, class T>
OutputIterator iota_n(OutputIterator first, Size n, T value)
{
        while (n--)
                *first++ = value++;
        return first;
}
Run Code Online (Sandbox Code Playgroud)

备选方案2)

template<class OutputIterator, class Size, class T>
OutputIterator iota_n(OutputIterator first, Size n, T value)
{
        return std::generate_n(first, n, [&](){ return value++; });
}    
Run Code Online (Sandbox Code Playgroud)

这两种方案都会产生优化编译器的等效代码吗?

更新:结合了@Marc Mutz的优点,也在目标点返回迭代器.这也是std::generate_nC++ 11与C++ 98相比更新的方式.

Ker*_* SB 10

作为一个随机的例子,我使用g++ -S -O2 -masm=intel(GCC 4.7.1,x86_32)编译了以下代码:

void fill_it_up(int n, int * p, int val)
{
    asm volatile("DEBUG1");
    iota_n(p, n, val);
    asm volatile("DEBUG2");
    iota_m(p, n, val);
    asm volatile("DEBUG3");
    for (int i = 0; i != n; ++i) { *p++ = val++; }
    asm volatile("DEBUG4");
}
Run Code Online (Sandbox Code Playgroud)

iota_n是第一个版本,iota_m第二个版本.这三个案例中的程序集如下:

    test    edi, edi
    jle .L4
    mov edx, eax
    neg edx
    lea ebx, [esi+edx*4]
    mov edx, eax
    lea ebp, [edi+eax]
    .p2align 4,,7
    .p2align 3
.L9:
    lea ecx, [edx+1]
    cmp ecx, ebp
    mov DWORD PTR [ebx-4+ecx*4], edx
    mov edx, ecx
    jne .L9
Run Code Online (Sandbox Code Playgroud)

随着-O3,三个版本也非常相似,但很多更长(使用条件的动作和punpcklqdq与此类似的).