Use function templates to accommodate other vector types #10
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
dspline
makes generous use of Rcpp Vector classes. Rcpp classes make sense when interfacing with directly with R code, but the use of Rcpp classes to represent vectors in internal, lower-level routines (e.g., evaluation of basis vectors) offers comparatively little advantage. Those functions do not use features unique to Rcpp classes (Rcpp sugar, attributes), nor methods implemented exclusively for Rcpp classes.At the same time, another package may want to link to
dspline
code for its efficient implementations of matrix construction, (in-place) multiplication, etc. That package might also be representing most of its internal objects using Eigen::VectorXd for numerical computation, and may want to avoid copying Eigen::VectorXd objects into Rcpp objects just to calldspline
routines.Function templates allow us to generalize a single function definition to accommodate different object types. The functions in utils.cpp would be implemented the same way whether it were using
Eigen::VectorXd
orstl::vector<double>
in lieu ofNumericVector
. Turning them into template functions tells the compiler to create three versions of each function. The compiler then uses type inference to decide which version to apply (or one can explicitly call a version of the function).This draft PR is an example of concept for how we could use function templates throughout Rcpp to generalize its code and make it more useful for external packages. (A more ambitious goal is to think about which parts of
dspline
/ glmgen pacakges can or should be implemented solely using, e.g., Eigen, with Rcpp[Eigen] used only to "glue" those functions to R, so that in the future we or others may be able to link to these C++ functions from other high-level languages. Even in that code, it makes sense to accommodate Rcpp Vectors to take advantage of the proxy model of memory. Function templates let us have the best of both worlds.)One point of dissatisfaction I have with function templates is that separate the declaration and definition of a template function is a messy business. In this draft PR, one can see a standard workaround for keeping the declaration in a header file and the definition in a cpp file: explicitly instantiating versions of the template function in the file where it is defined. (The basic problem is that if a template function is defined in a separate cpp file from where it is used, say with type
int
, then those files are compiled separately and the compiler doesn't know to create a version of the template function for typeint
, resulting a link error.)