Skip to content

const'ness (constivity?) in sugar::min/max #477

@dcdillon

Description

@dcdillon

The sugar::min and sugar::max classes (which to my mind should just be functions anyhow, but leaving that) have a cast operator to the typedef'ed STORAGE type. This operator is not defined as const because it actually modifies some private member variables. This is causing a problem with the latest fix for operator ambiguity in Matrix or Vector arithmetic operators.

I see no problem in moving these private member variables simply into the cast operator function and declaring the function as const. Does anyone else see any pitfalls?

I would propose changing:

template <int RTYPE, bool NA, typename T>
class Max {
public:
    typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;

    Max( const T& obj_) : obj(obj_) {}

    operator STORAGE() {
        max_ = obj[0] ;
        if( Rcpp::traits::is_na<RTYPE>( max_ ) ) return max_ ;

        R_xlen_t n = obj.size() ;
        for( R_xlen_t i=1; i<n; i++){
            current = obj[i] ;
            if( Rcpp::traits::is_na<RTYPE>( current ) ) return current;
            if( current > max_ ) max_ = current ;
        }
        return max_ ;
    }

private:
    const T& obj ;
    STORAGE min_, max_, current ;
} ;

to

template <int RTYPE, bool NA, typename T>
class Max {
public:
    typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;

    Max( const T& obj_) : obj(obj_) {}

    operator STORAGE() const {
        STORAGE min_, max_, current ;
        max_ = obj[0] ;
        if( Rcpp::traits::is_na<RTYPE>( max_ ) ) return max_ ;

        R_xlen_t n = obj.size() ;
        for( R_xlen_t i=1; i<n; i++){
            current = obj[i] ;
            if( Rcpp::traits::is_na<RTYPE>( current ) ) return current;
            if( current > max_ ) max_ = current ;
        }
        return max_ ;
    }

private:
    const T& obj ;
} ;

Alternatively, we could greatly simplify min/max by simply defining:

namespace Rcpp
{

template< int RTYPE, typename T >
typename traits::storage_type< RTYPE >::type max(const VectorBase< RTYPE, true, T > &x) {
    typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE;

    STORAGE max, current;

    max = x[0];

    if (traits::is_na<RTYPE>(max)) return max;

    R_xlen_t n = x.size();

    for (R_xlen_t i = 1; i < n; ++i)
    {
        current = x[i];
        if (traits::is_na<RTYPE>(current)) return current;
        if (current > max) max = current;
    }

    return max;
}

template< int RTYPE, typename T >
typename traits::storage_type< RTYPE >::type max(const VectorBase< RTYPE, false, T > &x) {
    typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE;

    STORAGE max, current;

    max = x[0];

    R_xlen_t n = x.size();

    for (R_xlen_t i = 1; i < n; ++i)
    {
        current = x[i];
        if (current > max) max = current;
    }

    return max;
}

} // namespace Rcpp

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions