From dbcc8c599119cfe8a61147a71e47210e3039f9e8 Mon Sep 17 00:00:00 2001 From: Romain Francois Date: Wed, 5 Aug 2020 12:23:05 +0200 Subject: [PATCH 1/2] handle enum with underlying type char --- cpp11test/src/test-as.cpp | 13 +++++++++++++ inst/include/cpp11/as.hpp | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cpp11test/src/test-as.cpp b/cpp11test/src/test-as.cpp index 9c65a689..b4e5d9cc 100644 --- a/cpp11test/src/test-as.cpp +++ b/cpp11test/src/test-as.cpp @@ -90,6 +90,19 @@ context("as_cpp-C++") { UNPROTECT(1); } + test_that("as_cpp(INTSEXP)") { + enum class Response: char { YES, NO, MAYBE }; + SEXP r = PROTECT(Rf_allocVector(INTSXP, 1)); + + for (Response e : {Response::YES, Response::NO, Response::MAYBE, static_cast(42)}) { + INTEGER(r)[0] = static_cast(e); + auto x = cpp11::as_cpp(r); + expect_true(x == e); + } + + UNPROTECT(1); + } + test_that("as_cpp(REALSXP)") { SEXP r = PROTECT(Rf_allocVector(REALSXP, 1)); REAL(r)[0] = 1.2; diff --git a/inst/include/cpp11/as.hpp b/inst/include/cpp11/as.hpp index bcadfc57..d1cddac2 100644 --- a/inst/include/cpp11/as.hpp +++ b/inst/include/cpp11/as.hpp @@ -96,7 +96,12 @@ enable_if_integral as_cpp(SEXP from) { template enable_if_enum as_cpp(SEXP from) { if (Rf_isInteger(from)) { - return static_cast(as_cpp::type>(from)); + using Type = typename std::conditional< + std::is_same::type>::value, + int, + typename std::underlying_type::type + >::type; + return static_cast(as_cpp(from)); } stop("Expected single integer value"); From a451f4ba569dcf9f435dc512a0332971974f5e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Fran=C3=A7ois?= Date: Thu, 6 Aug 2020 14:56:57 +0200 Subject: [PATCH 2/2] Update inst/include/cpp11/as.hpp Co-authored-by: Benjamin Kietzman --- inst/include/cpp11/as.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/inst/include/cpp11/as.hpp b/inst/include/cpp11/as.hpp index d1cddac2..3523f240 100644 --- a/inst/include/cpp11/as.hpp +++ b/inst/include/cpp11/as.hpp @@ -96,12 +96,13 @@ enable_if_integral as_cpp(SEXP from) { template enable_if_enum as_cpp(SEXP from) { if (Rf_isInteger(from)) { - using Type = typename std::conditional< - std::is_same::type>::value, - int, - typename std::underlying_type::type + using underlying_type = typename std::underlying_type::type; + using int_type = typename std::conditional< + std::is_same::value, + int, // as_cpp would trigger undesired string conversions + underlying_type >::type; - return static_cast(as_cpp(from)); + return static_cast(as_cpp(from)); } stop("Expected single integer value");