[Rcpp-devel] idiom for creating an informative message for an exception

Romain Francois romain at r-enthusiasts.com
Sat Dec 4 15:13:14 CET 2010


Le 02/12/10 22:15, Douglas Bates a écrit :
> In the lme4a package I mixed calls to Rf_error and throwing C++
> exceptions.  This is causing problems and I plan to replace the calls
> to Rf_error by exceptions so that there is a consistent approach.
>
> Many of the calls to Rf_error take advantage of the fact the Rf_error
> implicitly calls sprintf to create the error message.  Thus I have
> calls like
>
> 	if (!d_x.size() == d_nrow * d_ncol)
> 	    ::Rf_error("%s: Dim = (%d, %d) is inconsistent with x.size() = %d",
> 		       "ddenseMatrix::ddenseMatrix", d_nrow, d_ncol, d_x.size());
>
> Is there a similar idiom for creating an exception's "what" argument?
> I imagine I could add std::strings and maybe use some iostreams or
> something like that ...

Hello,

I've added the sprintf template, defined as:

template <int MAX_SIZE>
const char* sprintf( const char *format, ...) {
     static char buffer[MAX_SIZE];
     va_list(ap);
     va_start(ap, format);
     vsprintf( buffer, format, ap);
     va_end(ap);
     buffer[MAX_SIZE] = '\0';
     return strdup( buffer ) ;
}

so that we can do things like :

fx <- cxxfunction( , '
     return CharacterVector::create(
         sprintf<100>( "bla %d", 10 ),
         sprintf<100>( "bla %s %d", " bla" , 10)
         );
     ', plugin = "Rcpp", verbose = TRUE
)
fx()


This way, I think you can create your exception class like this:


fy <- cxxfunction( , '
     throw foo_exception( 10, 10, 10 ) ;
     ', includes = '

     class foo_exception : public std::exception {
         public:
             foo_exception( int nrow_, int ncol_, int size_):
                 nrow(nrow_), ncol(ncol_), size(size_){}
             inline const char* what() const throw(){
                 return sprintf<100>(
                     "%s: Dim = (%d, %d) is inconsistent with x.size() = 
%d",
                         "ddenseMatrix::ddenseMatrix", nrow, ncol, size
                     ) ;
             }
             ~foo_exception() throw(){}

         private:
             int nrow, ncol, size ;
     } ;


     ', plugin = "Rcpp", verbose = TRUE
)


 > tryCatch( fy(), error = function(e) writeLines( conditionMessage(e) ) )
ddenseMatrix::ddenseMatrix: Dim = (10, 10) is inconsistent with x.size() 
= 10


sprintf is a template, and static data is allocated with it. The 
parameter should be bug enough to host the full message.

one thing you can do is instantiate the template once :

const char* (*my_sprintf)(const char*, ...) = &sprintf<100> ;

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/gpCSpH : Evolution of Rcpp code size
|- http://bit.ly/hovakS : RcppGSL initial release
`- http://bit.ly/iaxTdO : parser 0.0-12




More information about the Rcpp-devel mailing list