vendredi 18 août 2017

Can an iterator be turned into a pointer?

In "13.7.3 async()" of "A Tour of C++" (first print), the following is provided as an example:

double comp4(vector<double>& v)
{
  if (v.size() < 10000)
    return accum(v.begin(), v.end(), 0.0);

  auto v0 = &v[0];
  auto sz = v.size();

  auto f0 = async(accum, v0, v0 + sz/4, 0.0);
  auto f1 = async(accum, v0 + sz/4, v0 + sz/2, 0.0);
  auto f2 = async(accum, v0 + sz/2, v0 + sz*3/4, 0.0);
  auto f3 = async(accum, v0 + sz*3/4, v0 + sz, 0.0);

  return f0.get() + f1.get() + f2.get() + f3.get();
}

where accum is defined as follows:

double accum(double* beg, double* end, double init)
{
  return accumulate(beg, end, init);
}

vector, async and accumulate are the standard library versions.

Running this produces the following error:

error: cannot convert ‘std::vector<double>::iterator {aka __gnu_cxx::__normal_iterator<double*, std::vector<double> >}’ to ‘double*’ for argument ‘1’ to ‘double accum(double*, double*, double)’
     return accum(v.begin(), v.end(), 0.0);

I can get this to work if I use return accum(&v[0], &v[0] + v.size(), 0.0); instead. Have I done something wrong in the original formulation? Should vector<double>::iterator be able to convert to double* or is this a mistake with the book? This issue doesn't seem to be mentioned in the errata for both the first and second printings of the book.

Aucun commentaire:

Enregistrer un commentaire