Вопрос

Saw this question, Best STL transform - like template function for ternary operators, thought it would be cool to make an narry transform for kicks and giggles.

So I threw this together, seems to work...with a caviate. My preincrement method is...odd to me. I couldn't figure out how to do with without unpacking. I expected the syntax to be something like (++args)... (similar to the deference syntax of (*args)...) but that returns an error. Anyone know how to do it?

#include <iostream>
#include <vector>

inline void preincrement(){}

template <typename T,typename... Ts>
inline void preincrement(T& t,Ts&... ts)
{
  ++t;
  preincrement(ts...);
}
template <class OutputIterator, class NArryOperator, class InputIterator, class... InputIterators>
OutputIterator transform_n(OutputIterator out_iter, NArryOperator oper, InputIterator iter1begin, InputIterator iter1end,InputIterators... args)
{
  for (; iter1begin != iter1end; ++out_iter,++iter1begin,preincrement(args...))
  {
    *out_iter = oper(*iter1begin,(*args)...);
  }
  return out_iter;
}

template <typename T>
struct noop
{
  T operator()(const T& val){return val;}
};

template <typename Ot,typename T,typename... Ts>
struct nsum
{
  Ot operator()(const T& t,const Ts&... ts)
  {
    return (Ot)t+nsum<Ot,Ts...>()(ts...);
  }
};

template <typename Ot, typename T>
struct nsum<Ot,T>
{
  Ot operator()(const T& t)
  {
    return (Ot)t;
  }
};

int main(int argc,char** argv)
{
  std::vector<int> rng;
  for (int i = 0; i < 10; i++) {rng.push_back(i);}
  std::vector<int> rng1 = rng;
  std::vector<int> rng2 = rng;
  std::vector<int> rng3 = rng;
  std::vector<float> out(rng.size());
  auto beg = out.begin();
  auto end = transform_n(beg,nsum<double,int,int,int,int>(),
  rng.begin(),rng.end(),
  rng1.begin(),
  rng2.begin(),
  rng3.begin());

  for (auto i = beg; i != end; ++i)
  {
    std::cout << *i << std::endl;
  }
}
Это было полезно?

Решение

A solution using postincrement directly:

template <class OutputIterator, class NArryOperator,
          class InputIterator, class... InputIterators>
OutputIterator transform_n(OutputIterator out_iter, NArryOperator oper,
                           InputIterator iter1begin, InputIterator iter1end,
                           InputIterators... args)
{
  while(iter1begin != iter1end)
  {
    *out_iter++ = oper(*iter1begin++, (*args++)...);
  }
  return out_iter;
}

About incrementing in the "increment-expression" of a for-statement:

You can't expand in the "increment-expression" of the for-statement; pack expansion is restricted to a few contexts, such that operator, overloads cannot apply [temp.variadic]/4. The usual tricks are required, such as expanding in a function call (what you used) or using a dummy array:

using iarr = int[];
for (; iter1begin != iter1end;
     ++out_iter,++iter1begin,(void)iarr{0, (++args,void(),0)...})
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top