[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