11
22// traits.h: Rcpp R/C++ interface class library -- support traits for vector
33//
4- // Copyright (C) 2010 - 2026 Dirk Eddelbuettel and Romain Francois
4+ // Copyright (C) 2010 - 2025 Dirk Eddelbuettel and Romain Francois
5+ // Copyright (C) 2026 Dirk Eddelbuettel, Romain Francois and Kevin Ushey
56//
67// This file is part of Rcpp.
78//
2425namespace Rcpp {
2526namespace traits {
2627
28+ // Kept out of line and marked cold so that the (almost never taken)
29+ // warning path doesn't bloat element access and block optimization of
30+ // hot loops, e.g. in sugar expressions.
31+ #if defined(__GNUC__)
32+ __attribute__ ((noinline, cold))
33+ #endif
34+ inline void warn_index_out_of_bounds (R_xlen_t i, R_xlen_t size) {
35+ warning (" subscript out of bounds (index %s >= vector size %s)" , i, size); // #nocov
36+ }
37+
2738 template <int RTYPE , template <class > class StoragePolicy = PreserveStorage >
2839 class r_vector_cache {
2940 public:
@@ -38,11 +49,12 @@ namespace traits{
3849
3950 inline void update ( const VECTOR & v ) {
4051 start = ::Rcpp::internal::r_vector_start<RTYPE >(v) ;
41- size = v. size ( );
52+ size = :: Rf_xlength (v. get__ () );
4253 }
4354
4455 inline iterator get () const { return start; }
4556 inline const_iterator get_const () const { return start; }
57+ inline R_xlen_t get_size () const { return size; }
4658
4759 inline proxy ref () { check_index (0 ); return start[0 ] ;}
4860 inline proxy ref (R_xlen_t i) { check_index (i); return start[i] ; }
@@ -55,7 +67,7 @@ namespace traits{
5567 void check_index (R_xlen_t i) const {
5668#ifndef RCPP_NO_BOUNDS_CHECK
5769 if (i >= size) {
58- warning ( " subscript out of bounds (index %s >= vector size %s) " , i, size); // #nocov
70+ warn_index_out_of_bounds ( i, size); // #nocov
5971 }
6072#endif
6173 }
@@ -80,6 +92,10 @@ namespace traits{
8092 }
8193 inline iterator get () const { return iterator ( proxy (*p, 0 ) ) ;}
8294 inline const_iterator get_const () const { return const_iterator ( const_proxy (*p, 0 ) ) ; }
95+ // Not cached: a size member here would change the layout of List and
96+ // CharacterVector, which packages pass by reference across
97+ // shared-library boundaries (see the note in Matrix.h).
98+ inline R_xlen_t get_size () const { return ::Rf_xlength (p->get__ ()); }
8399
84100 inline proxy ref () { check_index (0 ); return proxy (*p,0 ) ; }
85101 inline proxy ref (R_xlen_t i) { check_index (i); return proxy (*p,i);}
@@ -92,8 +108,9 @@ namespace traits{
92108
93109 void check_index (R_xlen_t i) const {
94110#ifndef RCPP_NO_BOUNDS_CHECK
95- if (i >= p->size ()) {
96- warning (" subscript out of bounds (index %s >= vector size %s)" , i, p->size ()); // #nocov
111+ R_xlen_t size = get_size () ;
112+ if (i >= size) {
113+ warn_index_out_of_bounds (i, size); // #nocov
97114 }
98115#endif
99116 }
0 commit comments