Skip to content

Commit 8951335

Browse files
jeroenclaude
andcommitted
Cover all integer index types via templated operator[] on wasm
The previous patch added a `long` overload to fix `c[long]` ambiguity on wasm32, but introduced a new ambiguity for `c[size_t]` (and any other integer type that is not exactly R_xlen_t or long), because the two member overloads then tie on a Conversion-rank index ICS. Replace the single `long` overload with a SFINAE-constrained template that accepts any integral type other than R_xlen_t and delegates to the R_xlen_t version with an explicit cast. The template always provides an identity match on the index, beating both the non-template R_xlen_t overload (which requires an integral conversion) and the built-in pointer subscript (which requires a user-defined conversion on the object). Compiled only when LONG_VECTOR_SUPPORT is not defined, so LP64 builds remain unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent aed58c1 commit 8951335

2 files changed

Lines changed: 16 additions & 8 deletions

File tree

ChangeLog

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
2026-06-23 Jeroen Ooms <jeroen@berkeley.edu>
22

33
* inst/include/Rcpp/vector/Vector.h (Vector::operator[]): Add a
4-
long-index overload on platforms without LONG_VECTOR_SUPPORT (such
5-
as wasm32) to avoid ambiguity with the built-in pointer subscript
6-
synthesised via the implicit Vector -> SEXP conversion
4+
templated integer-index overload on platforms without
5+
LONG_VECTOR_SUPPORT (such as wasm32) to avoid ambiguity with the
6+
built-in pointer subscript synthesised via the implicit
7+
Vector -> SEXP conversion
78

89
2026-06-18 Dirk Eddelbuettel <edd@debian.org>
910

inst/include/Rcpp/vector/Vector.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define Rcpp__vector__Vector_h
2222

2323
#include <Rcpp/vector/Subsetter.h>
24+
#include <type_traits>
2425

2526
namespace Rcpp{
2627

@@ -339,11 +340,17 @@ class Vector :
339340
inline const_Proxy operator[]( R_xlen_t i ) const { return cache.ref(i) ; }
340341
#ifndef LONG_VECTOR_SUPPORT
341342
// On platforms without long vector support (notably wasm32) R_xlen_t is
342-
// int while ptrdiff_t is long, which makes c[i] with a long index
343-
// ambiguous between this operator[] and the built-in pointer subscript
344-
// synthesised via the implicit Vector -> SEXP conversion.
345-
inline Proxy operator[]( long i ){ return cache.ref(i) ; }
346-
inline const_Proxy operator[]( long i ) const { return cache.ref(i) ; }
343+
// int while ptrdiff_t is long, so subscripting with any wider integer
344+
// type would otherwise be ambiguous with the built-in pointer subscript
345+
// synthesised via the implicit Vector -> SEXP conversion. The template
346+
// overloads below provide an exact-match member candidate for every
347+
// integer index type other than R_xlen_t itself.
348+
template <typename T>
349+
inline typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, R_xlen_t>::value, Proxy>::type
350+
operator[]( T i ){ return cache.ref(static_cast<R_xlen_t>(i)) ; }
351+
template <typename T>
352+
inline typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, R_xlen_t>::value, const_Proxy>::type
353+
operator[]( T i ) const { return cache.ref(static_cast<R_xlen_t>(i)) ; }
347354
#endif
348355

349356
inline Proxy operator()( const size_t& i) {

0 commit comments

Comments
 (0)