[Rcpp-devel] idiom for creating an informative message for an exception
romain at r-enthusiasts.com
romain at r-enthusiasts.com
Fri Dec 10 21:01:40 CET 2010
Le 10 déc. 2010 à 08:33 PM, Douglas Bates <bates at stat.wisc.edu> a écrit :
> On Sat, Dec 4, 2010 at 8:13 AM, Romain Francois
> <romain at r-enthusiasts.com> wrote:
>> 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:
>
> I think there is an off-by-one problem in this template. The maximum
> index in buffer is MAX_SIZE - 1, not MAX_SIZE. I suggest declaring
> buffer to be MAX_SIZE + 1
Oops.
Go ahead.
>> 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
>>
>>
>> _______________________________________________
>> Rcpp-devel mailing list
>> Rcpp-devel at lists.r-forge.r-project.org
>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>
More information about the Rcpp-devel
mailing list