Changelog
Source:NEWS.md
cppally (development version)
Bug fixes
Fixed a bug where matching on integer vectors with a non
NAnomatchvalue would still returnNA.Fixed a bug where getting
r_dfrows would return CHARSXP instead of STRSXP.Fixed a bug where
r_vec::applywould throw a compiler error when called on lists and character vectors.
Breaking changes
Sequences no longer abort on overflow, but instead silently return
NA.Removed
r_vec::subsetandr_factors::subsetas they didn’t thematically fit in with the rest of the members. The freesubsetfunction is still available.Renamed
common_lengthtolist_common_length.common_lengthnow accepts variadic inputs.Relocated various headers to and from the sugar folder.
r_factorsmember functionsget_codes,set_codes, andnew_codeshave been removed. The functionality of these can be achieved with the existing members.
r_function
New class
r_functionto safely call R functions from C++.New helper
pkg_envto return the environment of a package, allowing users to easily retrieve functions from specific packages, e.g.r_function("foo", pkg_env<"bar">()).
Improvements
cpp_sourcenow generates OpenMP flags, so its compiled functions can use both OpenMP SIMD vectorisation and multi-threaded execution (threads set viaset_threads()).Integer multiplication overflow handling is now more portable.
r_symnow constructs symbols from strings (const char*,r_str,r_str_view) under unwind protection, so R errors can no longer longjmp past C++ destructors.Sorting speed has been improved for both character vectors and numeric vectors. Sorting is faster for character vectors when there are a relatively high proportion of unique strings. Sorting is also dramatically faster for double vectors when all values in the vector are exact whole numbers.
n_uniquehas been sped-up for integer vectors.
New features
New
copymember forr_vec,r_factorsandr_df.copyshallow copies the vector by creating a fresh copy of the atomic data, without deep copying lists or attributes, just likeRf_shallow_duplicate.New by-group left-fold functional
reduce_by_group, allowing for very efficient binary reductions by-group.New function
list_recycleto recycle vectors of a list.New
r_sexpvisit helpersvisit_asandview_as.New
r_strmember functionis_utf8to check whether a string has valid UTF-8 encoding, which includes ASCII strings.New
r_strmember functionas_utf8to convert a string to a UTF-8 string. If the string is already a UTF-8 string, it is a no-op and simply returns the samer_str.New class
string_literalto facilitate compile-time string literal NTTP programming.cpp_evalgains a new argument,cppally_header, allowing one to compile expressions using the optional light header “cppally_light.hpp”.r_factorsgains a new member function,refactor, which creates a newr_factorsobject given a new set of levels.
cppally 1.1.0 (2026-07-12)
CRAN release: 2026-07-12
Breaking changes
Improved type-safety regarding implicit coercion of RScalar types. They now can implicitly coerce only to their wrapped types, whereas before they could implicitly coerce to that as well as other C types.
RTimeTypearithmetic has been deprecated and removed.Arithmetic involving
r_lglis now always promoted tor_int, matching R’s own semantics.common_math_t<T, U>now never returnsr_lgl, effectively treatingr_lglasr_int.
Bug fixes
Fixed bug where exclusion of concepts header was affecting vignette creation on macos.
Fixed incorrect NA handling of
r_dateandr_psxct.Fixed a bug where
identical()would returnfalsefor two genuinely identicalNA_real_values.NULLoptional arguments are now correctly handled. Vector, factor and data frame arguments can now beNULLto allow for optional argument programming from R.Fixed a bug where checking exact equality (via
identical) for C/C++ types was not compiling due to template ordering issue.
r_lgl (logical) semantics
r_lglcan now implicitly coerce toint(and onlyint), consistent with the other RScalar types.r_lglvalues are now always normalised on construction internally to either 0, 1, orNA.
Arithmetic
Integer overflow is now explicitly handled in all cppally arithmetic, returning
NAwhen detected. Integer addition and subtraction in particular are written using branchless or vectorisable code, enabling SIMD vectorisation.Integer in-place division
/=now matches R’s%/%(floored division), instead of C’s truncating division, e.g.-7L /= 2Lnow gives-4instead of-3. Division by zero orNAnow correctly returnsNAinstead of crashing the R session. Precision is also preserved for larger_int64values that previously round-tripped throughdouble.Scalar in-place arithmetic that narrows a wider result back to the left-hand type (e.g.
r_int += r_int64) now checks the value fits first, givingNAon overflow instead of a silently wrapped result.%now accepts mixed integer/float operands (e.g.r_int(7) % 2.5), promoting and flooring consistent with R’s%%.Vector in-place arithmetic (
+=,-=,*=,%=) now routes through the scalar operators, fixing a bug where mixed-width operations (e.g.r_vec<r_int> += r_vec<r_int64>) could silently truncate values, including turningNAinto0.
Improvements
Better errors when passing invalid types to template functions.
Constructing invalid dates and date-times now returns
NAinstead of an error.New concept
RNumberto represent number-based types liker_intandr_dbl.New member
is_nafor RScalar types, in addition to the equivalentis_nafree function.New member function
na()for RScalar classes.Relational operators have been extended to cover all RNumericType classes which includes
r_dateandr_psxct.
cppally 1.0.0 (2026-07-02)
CRAN release: 2026-07-02
First major release. cppally’s public API is now considered stable. While there may be structural changes to the r_df and r_raw classes in the future, cppally’s vector and scalar classes are considered stable.
Breaking changes
r_sexp.lengthhas been deprecated, in favour of the free functionlengthlength(r_df)now returns the number of rows instead of the number of cols, marking a shift in how cppally treats data frames. They are now seen as row-wise vectors.Setting attributes on plain
SEXPis now unsupported, e.g. viacppally::attr::set_attr. Use cppally types such asr_vector,r_factors,r_dfand in some casesr_sexpfor attribute manipulation.Various out-of-place or trivial to implement
r_vecmember functions have been removed.visit_vector,visit_sexpandview_sexphave been deprecated in favour of the more flexible constrainedr_sexpvisitors:r_sexp_visit,r_sexp_viewandr_sexp_mutate. These allow concepts and custom constraints to be applied directly on the lambda’s template parameter, e.g.r_sexp_visit(x, [&]<RVector T>(T vec){})— herexis dispatched as its concrete vector type and aborts at runtime if the underlying type isn’t anRVector.r_sexp_viewis the non-owning sibling: the wrapper handed to the lambda is a view (no extra protect), so it must not outlivex.r_sexp_mutateis for in-place mutation: it movesxinto the typed wrapper (making it the sole owner), callsf, then writes the result back.r_factorselements are now treated asr_strin member functions likegetandsetr_sexp_visitnow visitsr_nullasr_vec<r_sexp>(r_null), essentially treatingNULLas an empty list but without changing the underlying data.
For example, in the below pseudo-code, when x is r_null of type r_sexp, r_sexp_visit will disambiguate it as r_vec<r_sexp>(r_null), preserving its data as R’s NULL but assigning its type as r_vec<r_sexp> (list).
This preservation behaviour is not new, in fact all r_vec<T> vectors preserve r_null by design, allowing for efficient and easier attribute manipulation with vectors that may or may not be r_null. What is new is that previously r_null was not a visitable r_sexp object and now it is.
Data frames
r_dfis now fully integrated into cppally.New variadic function
make_dfto create in-line data frames.Various
r_dfmembers have been added to allow easier data frame manipulation.
std::vector
- Partial support for
std::vectorcoercion. The followingstd::vectorcoercion directions are supported:-
std::vector->std::vector -
std::vector->cppally::r_vec -
cppally::r_vec->std::vector
-
Any coercion between std::vector and cppally::r_vec is possible so long as the element coercions are supported by cppally::as
Regular sequences
New function
seqwhich behaves similarly tobase::seq.New function
sequencewhich is similar tobase::sequencebut accepts only scalar inputs.
Named vector hash lookups
For named vectors, lookup by name has been dramatically improved in C++ by introducing a hashing approach. It works in the following way: the first time a lookup is requested, a linear scan is done to find the named value. The second time triggers the hash map of name-value pairs to be built and cached with the vector. That second lookup is completed using the cached hash map and all subsequent lookups also use the hash map. The rationale for hashing on second lookup is covered in the ‘Automatic Names Hashing’ vignette.
A similar hashing approach is also used for r_factors, making conversions of strings to and from factor codes fast and analytically viable.
Copy-on-modify
cppally now supports copy-on-modify as an opt-in feature. This feature prevents accidentally overwriting data between shared objects, just like R. To opt-in, run cppally::use_copy_on_modify or set the copy_on_modify to TRUE in cpp_source.
The major downside of this feature is significantly slower element setting as every set must verify the object is not referenced by another object. This check is single-threaded and thus nearly all parallel cppally code is disabled as a safety precaution. If using copy-on-modify, it is recommended to avoid writing cppally registered R functions that rely on in-place modification.
pmap
Inspired by purrr::pmap and base::mapply, cppally::pmap is a C++ variadic function that supports applying custom C++ lambda functions across corresponding elements of multiple vectors.
With pmap it is trivial to calculate parallel statistics like max, min, etc. Example of C++ version of base::pmax applied to two vectors.
reduce
A left-fold reduction functional that successively applies a binary function along the elements of the vector (from left-to-right).
Example: maximum value across vector of doubles
Other changes
New alias of
r_vec,r_vector.Named-vector subsetting is now supported.
New C++ functions
combineandflatten.combineis a variadic function that allows for combining multiple vectors into one, similar tobase::cbut always casts vectors to the common type among them.flattenallows one to flatten a list of vectors into one vector of a specified type, similar tounlist(recursive = FALSE).Many functions that were originally
r_vec-only members are now free functions that also work onr_sexpas well asRCompositetypes, allowing for easier manipulation of lists.All C++ reference qualifiers (T&, T&&, const T&) are now supported for registered functions, including templated ones.
New concept
RVectorisablewhich encompasses types that are OMP friendly.New infix operator
IS_IN, identical to R’s%in%.New C++ function
coalesce().r_psxct.datetime_str()always appends “UTC” at the end to avoid time-zone ambiguity.
Bug fixes
When registering C++ functions, cppally.hpp is now included in the generated C++ code. Not including it caused issues when trying to compile functions that constructed factors.
Zero-length
r_vecvectors can now be constructed unambiguously viar_vec<T>(0).Math operations involving mixed types that included
r_dblare now correct when involvingNAvalues.