Skip to content

Const correctness of NumericVector iterators #209

@romainfrancois

Description

@romainfrancois

From this thread

This is related to David Shih's thread about modifying input arguments
but I think it needs its own thread.

I found a problem when I tried porting some Rcpp code to run outside of
Rcpp by providing my own NumericVector implementation based on STL
vectors. In Rcpp it is possible to obtain a non-constant iterator for a
constant vector, whereas STL does not allow this.

In particular, it is possible to modify a const NumericVector. The
compiler allows this because the actual contents of the NumericVector
are in auxiliary memory. But this breaks the abstraction of the
NumericVector class.

An example is given below. The "sumsquares" function calculates the sum
of squares of a vector. Internally, it calls the "workhorse" function,
which is declared to take a constant reference as an argument. So it
looks safe to pass the input vector to "workhorse" without copying.
However the implementation of "workhorse" does in fact alter the vector.

### BEGIN SS.cc
#include <Rcpp.h>

using Rcpp::NumericVector;

static double workhorse(NumericVector const &v);

// [[Rcpp::export]]
double sumsquares(NumericVector v)
{
   //Since workhorse takes a constant reference we think we do not need
   //to copy v...
   return workhorse(v);
}

double workhorse(NumericVector const &v)
{
   double y = 0;
   for (NumericVector::iterator i = v.begin(); i != v.end(); ++i) {
       double &x = *i;
       //... but this function does alter its argument
       x *= x;
       y += x;
   }
   return y;
}
### END SS.cc

In R we have

library(Rcpp)
sourceCpp("SS.cc")
x <- c(1,2,3)
sumsquares(x)
[1] 14
x #is modified
[1] 1 4 9

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions