2015-05-28 118 views
4

我可以在C++标准的草案N4431中找不到transform_n函数。为什么C++标准库中没有std :: transform_n函数?

这是故意的吗?如果不是的话,那么人们会如何为未来版本的标准提出建议?

这是我将如何实现它:

template<typename _InputIterator, typename Size, typename _OutputIterator, typename _UnaryOperation> 
_OutputIterator transform_n(_InputIterator __first, Size __n, _OutputIterator __result, _UnaryOperation __op) { 
    for(Size i=0;i<__n;++i) 
     *__result++ = __op(*__first++); 
    return __result; 
} 


template<typename _InputIterator1, typename Size, typename _InputIterator2, typename _OutputIterator, typename _BinaryOperation> 
_OutputIterator transform_n(_InputIterator1 __first1, Size __n, _InputIterator2 __first2, _OutputIterator __result, _BinaryOperation __binary_op) { 
    for(Size i=0;i<__n;++i) 
     *__result++ = __binary_op(*__first1++, *__first2++); 
    return __result; 
} 
+0

请参阅https://isocpp.org/std/submit-a-proposal。一定要拿出一些引人注目的用例。 – chris

+0

@TonyD:这不仅仅是因为你不能通过两次相同的输入迭代器,所以它可以节省你的时间。但是你可以使用带有lambda的'std :: generate_n'。 – rici

+5

我会更感兴趣的是在迭代器(或范围)本身编码,而不是每个算法都有一个'_n'版本。例如,Eric Niebler的[范围库](https://github.com/ericniebler/range-v3),它具有'take(N)'适配器,它采用范围的前N个元素。 –

回答

2

这里的另一种可能的实现,这表明已经有一个库函数具有等效功能:

template<typename _InputIterator, 
     typename _OutputIterator, 
     typename _UnaryOperation> 
_OutputIterator transform_n(_InputIterator __first, 
          size_t __n, 
          _OutputIterator __result, 
          _UnaryOperation __op) { 
     return std::generate_n(__result, __n, 
          [&__first, &__op]() -> decltype(auto) { 
           return __op(*__first++); 
          }); 
} 

由于@TonyD在提到注释,这有强制转换按顺序发生的效果,但如果输入迭代器参数实际上只是一个输入迭代器,则情况已经如此。

编辑:根据@ T.C。的建议,我将lambda改为返回类型为decltype(auto),如果我理解正确,它可以允许通过输出迭代器移动语义。这需要最近的编译器,因为它是一个C++ 14功能。

+1

lambda应该返回'decltype(auto)'。 –

+0

@ T.C:好的。我也做了它(正确的,我认为)通过generate_n的返回值。 – rici

+1

'decltype(auto)'的意思是让lambda返回到'__op'返回的内容。如果调用返回某个东西的引用,则不想复制 - 表示某些内容甚至可能不可复制! C++ 11相当于' - > decltype(/ *表达式返回* /)'。 TBH,获得正确的lambda是非常棘手的,我可以看到一个图书馆解决方案的争论。 –

相关问题