Skip to content

Commit 54fc431

Browse files
krlmlrDavisVaughan
andauthored
Add data_frame constructor that specifies the number of rows (#272)
* Allow passing number of rows from outside * Add forwarder, no idea why std::move() is necessary * Add tests and NEWS bullet * Run formatter * Continue using simpler constructor form here --------- Co-authored-by: Davis Vaughan <davis@posit.co>
1 parent 6a2bc9b commit 54fc431

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# cpp11 (development version)
22

3+
* New `writable::data_frame` constructor that also takes the number of rows as
4+
input. This accounts for the edge case where the input list has 0 columns but
5+
you'd still like to specify a known number of rows (#272).
6+
37
* `cpp11::writable::r_vector<T>::iterator` no longer implicitly deletes its
48
copy assignment operator (#360).
59

cpp11test/src/test-data_frame.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,28 @@ context("data_frame-C++") {
4343
expect_true(df.nrow() == 10);
4444
}
4545

46+
test_that("writable::data_frame::nrow works with 0x0 dfs") {
47+
SEXP x = PROTECT(Rf_allocVector(VECSXP, 0));
48+
49+
cpp11::writable::data_frame df(x);
50+
expect_true(df.nrow() == 0);
51+
52+
UNPROTECT(1);
53+
}
54+
55+
test_that("writable::data_frame::nrow works with 10x0 dfs (#272)") {
56+
SEXP x = PROTECT(Rf_allocVector(VECSXP, 0));
57+
58+
bool is_altrep = false;
59+
int nrow = 10;
60+
61+
// Manually specify `nrow` using special constructor
62+
cpp11::writable::data_frame df(x, is_altrep, nrow);
63+
expect_true(df.nrow() == 10);
64+
65+
UNPROTECT(1);
66+
}
67+
4668
test_that("writable::data_frame works") {
4769
using namespace cpp11::literals;
4870
cpp11::writable::data_frame df({"x"_nm = {1, 2, 3}, "y"_nm = {"a", "b", "c"}});

inst/include/cpp11/data_frame.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ namespace writable {
6767
class data_frame : public cpp11::data_frame {
6868
private:
6969
writable::list set_data_frame_attributes(writable::list&& x) {
70-
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -static_cast<int>(calc_nrow(x))};
70+
return set_data_frame_attributes(std::move(x), calc_nrow(x));
71+
}
72+
73+
writable::list set_data_frame_attributes(writable::list&& x, int nrow) {
74+
x.attr(R_RowNamesSymbol) = {NA_INTEGER, -nrow};
7175
x.attr(R_ClassSymbol) = "data.frame";
7276
return std::move(x);
7377
}
@@ -76,6 +80,8 @@ class data_frame : public cpp11::data_frame {
7680
data_frame(const SEXP data) : cpp11::data_frame(set_data_frame_attributes(data)) {}
7781
data_frame(const SEXP data, bool is_altrep)
7882
: cpp11::data_frame(set_data_frame_attributes(data), is_altrep) {}
83+
data_frame(const SEXP data, bool is_altrep, int nrow)
84+
: cpp11::data_frame(set_data_frame_attributes(data, nrow), is_altrep) {}
7985
data_frame(std::initializer_list<list> il)
8086
: cpp11::data_frame(set_data_frame_attributes(writable::list(il))) {}
8187
data_frame(std::initializer_list<named_arg> il)

0 commit comments

Comments
 (0)