From 6d8426c8d4a77630d2f40c7895b0f35972372e4f Mon Sep 17 00:00:00 2001 From: Mauricio Vargas Sepulveda Date: Mon, 29 Sep 2025 13:44:59 -0400 Subject: [PATCH] named_arg check with minimal changes --- inst/include/cpp11/r_vector.hpp | 60 +++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 576f4fe6..c5b69540 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -235,7 +235,9 @@ class r_vector : public cpp11::r_vector { proxy at(const r_string& name) const; void push_back(T value); - /// Implemented in `strings.hpp` + template ::value>::type* = nullptr> + void push_back(const std::string& value); // Pacha: r_string only (#406) void push_back(const named_arg& value); void pop_back(); @@ -256,6 +258,15 @@ class r_vector : public cpp11::r_vector { iterator find(const r_string& name) const; + /// Get the value at position without returning a proxy + /// This is useful when you need the actual value (e.g., for C-style printf functions) + /// that don't trigger implicit conversions from proxy types +#ifdef LONG_VECTOR_SUPPORT + T value(const int pos) const; +#endif + T value(const R_xlen_t pos) const; + T value(const size_type pos) const; + attribute_proxy> attr(const char* name) const; attribute_proxy> attr(const std::string& name) const; attribute_proxy> attr(SEXP name) const; @@ -865,7 +876,8 @@ inline r_vector::r_vector(std::initializer_list il) } unwind_protect([&] { - SEXP names = Rf_allocVector(STRSXP, capacity_); + SEXP names; + PROTECT(names = Rf_allocVector(STRSXP, capacity_)); Rf_setAttrib(data_, R_NamesSymbol, names); auto it = il.begin(); @@ -876,20 +888,30 @@ inline r_vector::r_vector(std::initializer_list il) // SAFETY: We've validated type and length ahead of this. const underlying_type elt = get_elt(value, 0); - // TODO: The equivalent ctor from `initializer_list` has a specialization - // for `` to translate `elt` to UTF-8 before assigning. Should we have - // that here too? `named_arg` doesn't do any checking here. - if (data_p_ != nullptr) { - data_p_[i] = elt; + if constexpr (std::is_same::value) { + // Translate to UTF-8 before assigning for string types + SEXP translated_elt = Rf_mkCharCE(Rf_translateCharUTF8(elt), CE_UTF8); + + if (data_p_ != nullptr) { + data_p_[i] = translated_elt; + } else { + // Handles STRSXP case. VECSXP case has its own specialization. + // We don't expect any ALTREP cases since we just freshly allocated `data_`. + set_elt(data_, i, translated_elt); + } } else { - // Handles STRSXP case. VECSXP case has its own specialization. - // We don't expect any ALTREP cases since we just freshly allocated `data_`. - set_elt(data_, i, elt); + if (data_p_ != nullptr) { + data_p_[i] = elt; + } else { + set_elt(data_, i, elt); + } } SEXP name = Rf_mkCharCE(it->name(), CE_UTF8); SET_STRING_ELT(names, i, name); } + + UNPROTECT(1); }); } @@ -1156,6 +1178,24 @@ inline typename r_vector::iterator r_vector::find(const r_string& name) co return end(); } +#ifdef LONG_VECTOR_SUPPORT +template +inline T r_vector::value(const int pos) const { + return value(static_cast(pos)); +} +#endif + +template +inline T r_vector::value(const R_xlen_t pos) const { + // Use the parent read-only class's operator[] which returns T directly + return cpp11::r_vector::operator[](pos); +} + +template +inline T r_vector::value(const size_type pos) const { + return value(static_cast(pos)); +} + template inline attribute_proxy> r_vector::attr(const char* name) const { return attribute_proxy>(*this, name);