Skip to content

Commit 6815d4b

Browse files
handle enum with underlying type char (#74)
Co-authored-by: Benjamin Kietzman <[email protected]>
1 parent edb6635 commit 6815d4b

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

cpp11test/src/test-as.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ context("as_cpp-C++") {
9090
UNPROTECT(1);
9191
}
9292

93+
test_that("as_cpp<enum:char>(INTSEXP)") {
94+
enum class Response: char { YES, NO, MAYBE };
95+
SEXP r = PROTECT(Rf_allocVector(INTSXP, 1));
96+
97+
for (Response e : {Response::YES, Response::NO, Response::MAYBE, static_cast<Response>(42)}) {
98+
INTEGER(r)[0] = static_cast<int>(e);
99+
auto x = cpp11::as_cpp<Response>(r);
100+
expect_true(x == e);
101+
}
102+
103+
UNPROTECT(1);
104+
}
105+
93106
test_that("as_cpp<double>(REALSXP)") {
94107
SEXP r = PROTECT(Rf_allocVector(REALSXP, 1));
95108
REAL(r)[0] = 1.2;

inst/include/cpp11/as.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,13 @@ enable_if_integral<T, T> as_cpp(SEXP from) {
9696
template <typename E>
9797
enable_if_enum<E, E> as_cpp(SEXP from) {
9898
if (Rf_isInteger(from)) {
99-
return static_cast<E>(as_cpp<typename std::underlying_type<E>::type>(from));
99+
using underlying_type = typename std::underlying_type<E>::type;
100+
using int_type = typename std::conditional<
101+
std::is_same<char, underlying_type>::value,
102+
int, // as_cpp<char> would trigger undesired string conversions
103+
underlying_type
104+
>::type;
105+
return static_cast<E>(as_cpp<int_type>(from));
100106
}
101107

102108
stop("Expected single integer value");

0 commit comments

Comments
 (0)