[Rcpp-commits] r1637 - pkg/Rcpp/inst/doc/Rcpp-sugar
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sat Jun 19 23:48:41 CEST 2010
Author: romain
Date: 2010-06-19 23:48:38 +0200 (Sat, 19 Jun 2010)
New Revision: 1637
Modified:
pkg/Rcpp/inst/doc/Rcpp-sugar/Rcpp-sugar.Rnw
Log:
some implementation details documented
Modified: pkg/Rcpp/inst/doc/Rcpp-sugar/Rcpp-sugar.Rnw
===================================================================
--- pkg/Rcpp/inst/doc/Rcpp-sugar/Rcpp-sugar.Rnw 2010-06-19 18:48:47 UTC (rev 1636)
+++ pkg/Rcpp/inst/doc/Rcpp-sugar/Rcpp-sugar.Rnw 2010-06-19 21:48:38 UTC (rev 1637)
@@ -399,6 +399,123 @@
\section{Implementation}
+\subsection{The curiously recurring template pattern}
+
+Expression templates such as those used by \sugar~use a technique
+called the \emph{Curiously Recurring Template Pattern} (CRTP). The general
+form of CRTP is:
+
+<<lang=cpp>>=
+// The Curiously Recurring Template Pattern (CRTP)
+template <typename T>
+struct base {
+ // ...
+};
+struct derived : base<derived> {
+ // ...
+};
+@
+
+The \texttt{base} class is templated by the class that derives from it :
+\texttt{derived}. This shifts the relationship between a base class and a derived
+class as it allows the base class to access methods of the derived class.
+
+\subsection{The VectorBase class}
+
+The CRTP is used as the basis for \sugar~with the \texttt{VectorBase}
+class template. All sugar expression derive from one class generated by the
+\texttt{VectorBase} template. The current definition of \texttt{VectorBase}
+is given here:
+
+<<lang=cpp>>=
+template <int RTYPE, bool na, typename VECTOR>
+class VectorBase {
+public:
+ struct r_type : traits::integral_constant<int,RTYPE>{} ;
+ struct can_have_na : traits::integral_constant<bool,na>{} ;
+ typedef typename traits::storage_type<RTYPE>::type stored_type ;
+
+ VECTOR& get_ref(){
+ return static_cast<VECTOR&>(*this) ;
+ }
+
+ inline stored_type operator[]( int i) const {
+ return static_cast<const VECTOR*>(this)->operator[](i) ;
+ }
+
+ inline int size() const { return static_cast<const VECTOR*>(this)->size() ; }
+
+ /* definition ommited here */
+ class iterator ;
+
+ inline iterator begin() const { return iterator(*this, 0) ; }
+ inline iterator end() const { return iterator(*this, size() ) ; }
+}
+@
+
+The \texttt{VectorBase} template has three parameters:
+
+\begin{itemize}
+\item \texttt{RTYPE}: This controls the type of expression (INTSXP, REALSXP, ...)
+\item \texttt{na}: This embeds in the derived type the information that instances
+can contain missing values. \pkg{Rcpp} vector types (\texttt{IntegerVector}, ...)
+derive from \texttt{VectorBase} with this parameter set to \texttt{true} because
+there is no way to know at compile time if the vector contains missing values.
+However, this parameter is set to \texttt{false} for types that are generated
+by sugar expressions that are guaranteed to produce expressions that are
+without missing values. And example of that is the \texttt{is\_na} function. This
+parameter is used in several places as part of the compile time dispatch to limit
+the occurence of redundant operations.
+\item \texttt{VECTOR}: This parameter is the key of \sugar. This is the
+manifestation of CRTP. The indexing operator and the \texttt{size} method
+of \texttt{VectorBase} use a static cast of \texttt{this} to the \texttt{VECTOR}
+type to forward calls to the actual method of the derived class.
+\end{itemize}
+
+\subsection{Example : sapply}
+
+As an example, the current implementation of \texttt{sapply}, supported by
+the template class \texttt{Rcpp::sugar::Sapply} is given below:
+
+<<lang=cpp>>=
+template <int RTYPE, bool NA, typename T, typename Function>
+class Sapply : public VectorBase<
+ Rcpp::traits::r_sexptype_traits<
+ typename ::Rcpp::traits::result_of<Function>::type
+ >::rtype ,
+ true ,
+ Sapply<RTYPE,NA,T,Function>
+> {
+public:
+ const static int RESULT_R_TYPE = Rcpp::traits::r_sexptype_traits<
+ typename ::Rcpp::traits::result_of<Function>::type
+ >::rtype ;
+ typedef Rcpp::VectorBase<RTYPE,NA,T> VEC ;
+ typedef typename ::Rcpp::traits::result_of<Function>::type result_type ;
+ typedef typename Rcpp::traits::r_vector_element_converter<RESULT_R_TYPE>::type converter_type ;
+ typedef typename Rcpp::traits::storage_type<RESULT_R_TYPE>::type STORAGE ;
+
+ Sapply( const VEC& vec_, Function fun_ ) : vec(vec_), fun(fun_){}
+
+ inline STORAGE operator[]( int i ) const {
+ return converter_type::get( fun( vec[i] ) );
+ }
+ inline int size() const { return vec.size() ; }
+
+private:
+ const VEC& vec ;
+ Function fun ;
+} ;
+
+} // sugar
+
+template <int RTYPE, bool _NA_, typename T, typename Function >
+inline sugar::Sapply<RTYPE,_NA_,T,Function>
+sapply( const Rcpp::VectorBase<RTYPE,_NA_,T>& t, Function fun ){
+ return sugar::Sapply<RTYPE,_NA_,T,Function>( t, fun ) ;
+}
+@
+
\bibliographystyle{abbrvnat}
\bibliography{Rcpp}
More information about the Rcpp-commits
mailing list