r-lib / cpp11

cpp11 helps you to interact with R objects using C++ code.
https://cpp11.r-lib.org/
Other
199 stars 46 forks source link

attributes ignored on non-`writable` objects during explicit set or construction #237

Closed vspinu closed 2 years ago

vspinu commented 3 years ago

#include "cpp11.hpp"
using namespace cpp11::literals;

[[cpp11::register]]
cpp11::data_frame test_wrong() {
  cpp11::doubles time({123456});
  time.attr("class") = cpp11::strings({"POSIXct", "POSIXt"});
  time.attr("tzone") = cpp11::strings({"UTC"});
  return cpp11::data_frame({
      "time"_nm = time
    });
}

[[cpp11::register]]
cpp11::data_frame test_right() {
  cpp11::writable::doubles time({123456});
  time.attr("class") = cpp11::strings({"POSIXct", "POSIXt"});
  time.attr("tzone") = cpp11::strings({"UTC"});
  return cpp11::writable::data_frame({
      "time"_nm = time
    });
}
> str(test_wrong())
List of 1
 $ time: num 123456
> str(test_right())
'data.frame':   1 obs. of  1 variable:
 $ time: POSIXct, format: "1970-01-02 10:17:36"

Issues:

  1. setting attributes on non-writable objects has no effect but does not trigger compile or run-time errors
  2. initialization list cpp11::data_frame constructor produces a list instead of a data frame
jimhester commented 2 years ago

Thanks for opening the issue with reproducible examples! They are a large help.

Fixed by https://github.com/r-lib/cpp11/commit/547a4947e28a1398de67b2391c25e0aaa24c6aac and https://github.com/r-lib/cpp11/commit/7312b66eee5c9f84947f06f85fbca7fbcfb77bdc

vspinu commented 2 years ago

@jimhester 7312b66 actually broke my second example, which I believe is valid.

#include "cpp11.hpp"
using namespace cpp11::literals;

[[cpp11::register]]
cpp11::data_frame test_right() {
  cpp11::writable::doubles time({123456});
  time.attr("class") = cpp11::strings({"POSIXct", "POSIXt"});
  time.attr("tzone") = cpp11::strings({"UTC"});
  return cpp11::writable::data_frame({
      "time"_nm = time
    });
}
/tmp/tmp.cpp:9:46: error: call of overloaded ‘r_vector(<brace-enclosed initializer list>)’ is ambiguous
   time.attr("tzone") = cpp11::strings({"UTC"});
                                              ^
jimhester commented 2 years ago

In this case there is no need for the explicit cpp11::strings() constructor e.g.

cpp11::cpp_source(code = '#include <cpp11.hpp>
  using namespace cpp11::literals;
  [[cpp11::register]]
  cpp11::data_frame test_right() {
    cpp11::writable::doubles time({123456});
    time.attr("class") = {"POSIXct", "POSIXt"};
    time.attr("tzone") = {"UTC"};
    return cpp11::writable::data_frame({
      "time"_nm = time
    });
  }
  ')

test_right()
#>                  time
#> 1 1970-01-02 10:17:36

Created on 2021-10-29 by the reprex package (v2.0.1)

vspinu commented 2 years ago

I see. Thanks!