From 1d9a5497ef313038e5a10961f34a8a8d3cb58706 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 07:48:48 -0500 Subject: [PATCH 01/11] First step of simplifying compiler checks There is more that can be done but each removal of a #DEFINE needs to check exactly where it is used. The bottom part of compiler.h still spans a grid over C++0x/TR1 to see if unordered map and set are a given (as in C++11 or later) which together with other calls of 'C++11 it is now' can simplify but we need to carefully walk this through the rest of the code and not just delete here as we'd keep unnecessary #define 'orphans' around. --- inst/include/Rcpp/platform/compiler.h | 126 ++++++++------------- inst/include/Rcpp/sugar/functions/sapply.h | 10 +- 2 files changed, 54 insertions(+), 82 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index bf60b189d..3ce7bee23 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -1,8 +1,6 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -// // compiler.h: Rcpp R/C++ interface class library -- check compiler // -// Copyright (C) 2012 - 2013 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey +// Copyright (C) 2012 - 2025 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey // // This file is part of Rcpp. // @@ -43,99 +41,72 @@ # error "This compiler is not supported" #endif +#if __cplusplus < 201103L +# error "The C++ compilation standard is too old: use C++11 or newer." +#endif + #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - // g++ 4.5 does not seem to like some of the fast indexing - #if GCC_VERSION >= 40500 - #define IS_GCC_450_OR_LATER - #endif - // g++ 4.6 switches from exception_defines.h to bits/exception_defines.h - #if GCC_VERSION < 40600 - #define IS_EARLIER_THAN_GCC_460 - #endif - #if GCC_VERSION >= 40600 - #define IS_GCC_460_OR_LATER - #endif #endif -// Check for the presence of C++0x (or later) support -#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) - #define RCPP_USING_CXX0X_OR_LATER -#endif +// TODO: Clean in a subsequent round +#define RCPP_USING_CXX0X_OR_LATER -// Check C++0x/11 features +// Check C++11 features (could/should work generally) #if defined(__INTEL_COMPILER) - #if __cplusplus >= 201103L - #define RCPP_USING_CXX11 - #if __INTEL_COMPILER >= 1210 - #define HAS_VARIADIC_TEMPLATES - #endif - #if __INTEL_COMPILER >= 1100 - #define HAS_STATIC_ASSERT - #endif + #define RCPP_USING_CXX11 + #if __INTEL_COMPILER >= 1210 + #define HAS_VARIADIC_TEMPLATES + #endif + #if __INTEL_COMPILER >= 1100 + #define HAS_STATIC_ASSERT #endif #elif defined(__clang__) - #if __cplusplus >= 201103L - #define RCPP_USING_CXX11 - #if __has_feature(cxx_variadic_templates) - #define HAS_VARIADIC_TEMPLATES - #endif - #if __has_feature(cxx_static_assert) - #define HAS_STATIC_ASSERT - #endif + #define RCPP_USING_CXX11 + #if __has_feature(cxx_variadic_templates) + #define HAS_VARIADIC_TEMPLATES + #endif + #if __has_feature(cxx_static_assert) + #define HAS_STATIC_ASSERT #endif #elif defined(__GNUC__) - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - #if GCC_VERSION >= 40300 - #define HAS_VARIADIC_TEMPLATES - #define HAS_STATIC_ASSERT - #endif + #define RCPP_USING_CXX11 + #if __has_feature(cxx_variadic_templates) + #define HAS_VARIADIC_TEMPLATES + #endif + #if __has_feature(cxx_static_assert) + #define HAS_STATIC_ASSERT #endif - #if GCC_VERSION >= 40800 && __cplusplus >= 201103L - #define RCPP_USING_CXX11 - #endif #endif -// Check C++0x headers +// Check C++0x headers (TODO remove when no longer needed below) #include #if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) - #if defined(__GLIBCXX__) && defined(__GXX_EXPERIMENTAL_CXX0X__) - #if GCC_VERSION >= 40400 - #define HAS_CXX0X_UNORDERED_MAP - #define HAS_CXX0X_UNORDERED_SET - #define HAS_CXX0X_INITIALIZER_LIST - #endif - #endif + #define HAS_CXX0X_UNORDERED_MAP + #define HAS_CXX0X_UNORDERED_SET + #define HAS_CXX0X_INITIALIZER_LIST #elif defined(__clang__) - #if __cplusplus >= 201103L - #if __has_include() - #define HAS_CXX0X_UNORDERED_MAP - #endif - #if __has_include() - #define HAS_CXX0X_UNORDERED_SET - #endif - #if __has_include() - #define HAS_CXX0X_INITIALIZER_LIST - #endif + #if __has_include() + #define HAS_CXX0X_UNORDERED_MAP + #endif + #if __has_include() + #define HAS_CXX0X_UNORDERED_SET + #endif + #if __has_include() + #define HAS_CXX0X_INITIALIZER_LIST #endif #endif -// Check TR1 Headers +// Check TR1 Headers (TODO remove when no longer needed below) #if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) - #if defined(__GLIBCXX__) - #if GCC_VERSION >= 40400 || ( GCC_VERSION >= 40201 && defined(__APPLE__) ) - #define HAS_TR1_UNORDERED_MAP - #define HAS_TR1_UNORDERED_SET - #endif - #endif + #define HAS_TR1_UNORDERED_MAP + #define HAS_TR1_UNORDERED_SET #elif defined(__clang__) - #if __cplusplus >= 201103L - #if __has_include() - #define HAS_TR1_UNORDERED_MAP - #endif - #if __has_include() - #define HAS_TR1_UNORDERED_SET - #endif + #if __has_include() + #define HAS_TR1_UNORDERED_MAP + #endif + #if __has_include() + #define HAS_TR1_UNORDERED_SET #endif #endif @@ -144,10 +115,11 @@ #endif // Conditionally include headers -#ifdef HAS_CXX0X_INITIALIZER_LIST +// #ifdef HAS_CXX0X_INITIALIZER_LIST #include -#endif +// #endif +// TODO: Simplify further: First case should work generally #ifdef RCPP_USING_CXX11 #if defined(HAS_CXX0X_UNORDERED_MAP) #include diff --git a/inst/include/Rcpp/sugar/functions/sapply.h b/inst/include/Rcpp/sugar/functions/sapply.h index 49ed29a3e..f5ee94449 100644 --- a/inst/include/Rcpp/sugar/functions/sapply.h +++ b/inst/include/Rcpp/sugar/functions/sapply.h @@ -21,9 +21,8 @@ #ifndef Rcpp__sugar__sapply_h #define Rcpp__sugar__sapply_h -#if defined(RCPP_USING_CXX0X_OR_LATER) - #include // ::std::result_of -#endif +// This used to be conditional on a define and test in compiler.h +#include // ::std::result_of namespace Rcpp{ namespace sugar{ @@ -31,7 +30,7 @@ namespace sugar{ template struct sapply_application_result_of { -#if defined(RCPP_USING_CXX0X_OR_LATER) +#if __cplusplus >= 201103L #if __cplusplus < 201703L // deprecated by C++17, removed by C++2020, see https://en.cppreference.com/w/cpp/types/result_of typedef typename ::std::result_of::type type; @@ -40,9 +39,10 @@ struct sapply_application_result_of typedef typename ::std::invoke_result::type type; #endif #else + // TODO this else branch can likely go typedef typename ::Rcpp::traits::result_of::type type; #endif -} ; +}; // template // using sapply_application_result_of_t = typename sapply_application_result_of::type; From f1956608d4296991f21ce8910f5c4d8a5afc3fa3 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 08:12:56 -0500 Subject: [PATCH 02/11] Do not rely on __has_feature() for g++ Given that we test for C++11 we can assume variadic templates and just use the #define. Can likely be generalized to icc and clang too. --- inst/include/Rcpp/platform/compiler.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index 3ce7bee23..ef625cc40 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -70,13 +70,10 @@ #define HAS_STATIC_ASSERT #endif #elif defined(__GNUC__) + // given the check about __cplusplus we can unconditionally define #define RCPP_USING_CXX11 - #if __has_feature(cxx_variadic_templates) - #define HAS_VARIADIC_TEMPLATES - #endif - #if __has_feature(cxx_static_assert) - #define HAS_STATIC_ASSERT - #endif + #define HAS_VARIADIC_TEMPLATES + #define HAS_STATIC_ASSERT #endif // Check C++0x headers (TODO remove when no longer needed below) From 2665b4d379195ef401662117fca2a865c26df1c6 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 08:20:24 -0500 Subject: [PATCH 03/11] Expand macos matrix to macos-13, simplify via r-ci with bootstrap --- .github/workflows/macos.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index c86c6350e..40c40340a 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -14,7 +14,8 @@ jobs: strategy: matrix: include: - - {os: macOS-latest} + - {os: macos-latest} + - {os: macos-13} #- {os: ubuntu-latest} runs-on: ${{ matrix.os }} @@ -24,10 +25,7 @@ jobs: uses: actions/checkout@v4 - name: Setup - uses: eddelbuettel/github-actions/r-ci-setup@master - - - name: Bootstrap - run: ./run.sh bootstrap + uses: eddelbuettel/github-actions/r-ci@master - name: Dependencies run: ./run.sh install_deps From 39f3c422bf0a9c77fd0da35df69efda11951f860 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 08:42:20 -0500 Subject: [PATCH 04/11] No longer provide fallback for unordered_{set,map} which are given Removes one if/else use in table.h for map, none for set --- inst/include/Rcpp/platform/compiler.h | 32 ++++++++++---------- inst/include/Rcpp/sugar/functions/table.h | 37 +---------------------- 2 files changed, 17 insertions(+), 52 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index ef625cc40..670323bba 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -122,38 +122,38 @@ #include #define RCPP_USING_UNORDERED_MAP #define RCPP_UNORDERED_MAP std::unordered_map - #else - #include - #define RCPP_USING_MAP - #define RCPP_UNORDERED_MAP std::map + // #else + // #include + // #define RCPP_USING_MAP + // #define RCPP_UNORDERED_MAP std::map #endif #if defined(HAS_CXX0X_UNORDERED_SET) #include #define RCPP_USING_UNORDERED_SET #define RCPP_UNORDERED_SET std::unordered_set - #else - #include - #define RCPP_USING_SET - #define RCPP_UNORDERED_SET std::set + // #else + // #include + // #define RCPP_USING_SET + // #define RCPP_UNORDERED_SET std::set #endif #else #if defined(HAS_TR1_UNORDERED_MAP) #include #define RCPP_USING_TR1_UNORDERED_MAP #define RCPP_UNORDERED_MAP std::tr1::unordered_map - #else - #include - #define RCPP_USING_MAP - #define RCPP_UNORDERED_MAP std::map + // #else + // #include + // #define RCPP_USING_MAP + // #define RCPP_UNORDERED_MAP std::map #endif #if defined(HAS_TR1_UNORDERED_SET) #include #define RCPP_USING_TR1_UNORDERED_SET #define RCPP_UNORDERED_SET std::tr1::unordered_set - #else - #include - #define RCPP_USING_SET - #define RCPP_UNORDERED_SET std::set + // #else + // #include + // #define RCPP_USING_SET + // #define RCPP_UNORDERED_SET std::set #endif #endif diff --git a/inst/include/Rcpp/sugar/functions/table.h b/inst/include/Rcpp/sugar/functions/table.h index 2cd647ca5..74cb01b20 100644 --- a/inst/include/Rcpp/sugar/functions/table.h +++ b/inst/include/Rcpp/sugar/functions/table.h @@ -1,8 +1,6 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- -// // table.h: Rcpp R/C++ interface class library -- table match // -// Copyright (C) 2012 - 2013 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey +// Copyright (C) 2012 - 2025 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey // // This file is part of Rcpp. // @@ -55,36 +53,6 @@ class Grabber{ R_xlen_t index ; } ; -// we define a different Table class depending on whether we are using -// std::map or not -#ifdef RCPP_USING_MAP - -template -class Table { -public: - typedef typename Rcpp::traits::storage_type::type STORAGE ; - - Table( const TABLE_T& table ): hash() { - std::for_each( table.begin(), table.end(), Inserter(hash) ) ; - } - - inline operator IntegerVector() const { - R_xlen_t n = hash.size() ; - IntegerVector result = no_init(n) ; - CharacterVector names = no_init(n) ; - std::for_each( hash.begin(), hash.end(), Grabber(result, names) ) ; - result.names() = names ; - return result ; - } - -private: - typedef RCPP_UNORDERED_MAP >HASH ; - typedef CountInserter Inserter ; - HASH hash ; -}; - -#else - template class Table { public: @@ -118,8 +86,6 @@ class Table { }; -#endif // USING_RCPP_MAP - } // sugar template @@ -130,4 +96,3 @@ inline IntegerVector table( const VectorBase& x ){ } // Rcpp #endif - From d2c859aa7ebf84e9a9a27d7c9954b4d770226925 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 09:22:31 -0500 Subject: [PATCH 05/11] Further cleanup --- inst/include/Rcpp/String.h | 16 +--- inst/include/Rcpp/platform/compiler.h | 104 ++++++++++++-------------- inst/include/Rcpp/sugar/sets.h | 47 +++--------- man/evalCpp.Rd | 23 +++--- src/api.cpp | 54 +++---------- 5 files changed, 82 insertions(+), 162 deletions(-) diff --git a/inst/include/Rcpp/String.h b/inst/include/Rcpp/String.h index 8316acee1..f1cb751cd 100644 --- a/inst/include/Rcpp/String.h +++ b/inst/include/Rcpp/String.h @@ -734,24 +734,14 @@ namespace Rcpp { } // Rcpp -/** hash can be in std or std::tr1 */ -#if defined(RCPP_USING_CXX11) || defined(HAS_TR1) -namespace std -{ -#ifndef RCPP_USING_CXX11 -namespace tr1 { -#endif +/** hash via std */ +namespace std { template <> - struct hash - { + struct hash { size_t operator()(const Rcpp::String & s) const{ return hash()(s.get_cstring()); } }; -#ifndef RCPP_USING_CXX11 -} -#endif } -#endif #endif diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index 670323bba..9162b717b 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -76,49 +76,37 @@ #define HAS_STATIC_ASSERT #endif -// Check C++0x headers (TODO remove when no longer needed below) +// C++11 features -- that used to be carefully tested for or worked around via CXX0X / TR1 #include -#if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) - #define HAS_CXX0X_UNORDERED_MAP - #define HAS_CXX0X_UNORDERED_SET - #define HAS_CXX0X_INITIALIZER_LIST -#elif defined(__clang__) - #if __has_include() - #define HAS_CXX0X_UNORDERED_MAP - #endif - #if __has_include() - #define HAS_CXX0X_UNORDERED_SET - #endif - #if __has_include() - #define HAS_CXX0X_INITIALIZER_LIST - #endif -#endif - -// Check TR1 Headers (TODO remove when no longer needed below) -#if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) - #define HAS_TR1_UNORDERED_MAP - #define HAS_TR1_UNORDERED_SET -#elif defined(__clang__) - #if __has_include() - #define HAS_TR1_UNORDERED_MAP - #endif - #if __has_include() - #define HAS_TR1_UNORDERED_SET - #endif -#endif +#define HAS_CXX0X_UNORDERED_MAP +#define HAS_CXX0X_UNORDERED_SET +#define HAS_CXX0X_INITIALIZER_LIST + +// // Check TR1 Headers (TODO remove when no longer needed below) +// #if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) +// #define HAS_TR1_UNORDERED_MAP +// #define HAS_TR1_UNORDERED_SET +// #elif defined(__clang__) +// #if __has_include() +// #define HAS_TR1_UNORDERED_MAP +// #endif +// #if __has_include() +// #define HAS_TR1_UNORDERED_SET +// #endif +// #endif -#if defined(HAS_TR1_UNORDERED_MAP) && defined(HAS_TR1_UNORDERED_SET) -#define HAS_TR1 -#endif +// #if defined(HAS_TR1_UNORDERED_MAP) && defined(HAS_TR1_UNORDERED_SET) +// #define HAS_TR1 +// #endif // Conditionally include headers // #ifdef HAS_CXX0X_INITIALIZER_LIST #include // #endif -// TODO: Simplify further: First case should work generally -#ifdef RCPP_USING_CXX11 - #if defined(HAS_CXX0X_UNORDERED_MAP) +// // TODO: Simplify further: First case should work generally +// #ifdef RCPP_USING_CXX11 +// #if defined(HAS_CXX0X_UNORDERED_MAP) #include #define RCPP_USING_UNORDERED_MAP #define RCPP_UNORDERED_MAP std::unordered_map @@ -126,8 +114,8 @@ // #include // #define RCPP_USING_MAP // #define RCPP_UNORDERED_MAP std::map - #endif - #if defined(HAS_CXX0X_UNORDERED_SET) + // #endif + // #if defined(HAS_CXX0X_UNORDERED_SET) #include #define RCPP_USING_UNORDERED_SET #define RCPP_UNORDERED_SET std::unordered_set @@ -135,27 +123,27 @@ // #include // #define RCPP_USING_SET // #define RCPP_UNORDERED_SET std::set - #endif -#else - #if defined(HAS_TR1_UNORDERED_MAP) - #include - #define RCPP_USING_TR1_UNORDERED_MAP - #define RCPP_UNORDERED_MAP std::tr1::unordered_map - // #else - // #include - // #define RCPP_USING_MAP - // #define RCPP_UNORDERED_MAP std::map - #endif - #if defined(HAS_TR1_UNORDERED_SET) - #include - #define RCPP_USING_TR1_UNORDERED_SET - #define RCPP_UNORDERED_SET std::tr1::unordered_set - // #else - // #include - // #define RCPP_USING_SET - // #define RCPP_UNORDERED_SET std::set - #endif -#endif + // #endif +// #else +// #if defined(HAS_TR1_UNORDERED_MAP) +// #include +// #define RCPP_USING_TR1_UNORDERED_MAP +// #define RCPP_UNORDERED_MAP std::tr1::unordered_map +// // #else +// // #include +// // #define RCPP_USING_MAP +// // #define RCPP_UNORDERED_MAP std::map +// #endif +// #if defined(HAS_TR1_UNORDERED_SET) +// #include +// #define RCPP_USING_TR1_UNORDERED_SET +// #define RCPP_UNORDERED_SET std::tr1::unordered_set +// // #else +// // #include +// // #define RCPP_USING_SET +// // #define RCPP_UNORDERED_SET std::set +// #endif +// #endif #ifdef __GNUC__ #define RCPP_HAS_DEMANGLING diff --git a/inst/include/Rcpp/sugar/sets.h b/inst/include/Rcpp/sugar/sets.h index fa432bfd1..e1aaaec2e 100644 --- a/inst/include/Rcpp/sugar/sets.h +++ b/inst/include/Rcpp/sugar/sets.h @@ -1,8 +1,6 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- -// // sets.h: Rcpp R/C++ interface class library -- // -// Copyright (C) 2012 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2012 - 2025 Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // @@ -22,40 +20,17 @@ #ifndef Rcpp__sugar__sets_h #define Rcpp__sugar__sets_h -#if __cplusplus >= 201103L - #define RCPP_UNORDERED_SET std::unordered_set - #define RCPP_UNORDERED_MAP std::unordered_map - - namespace std { - template<> - struct hash { - std::size_t operator()(const Rcpp::String& key) const { - return pointer_hasher( key.get_sexp() ) ; - } - hash pointer_hasher ; - }; - } - -#elif defined(HAS_TR1_UNORDERED_SET) - #define RCPP_UNORDERED_SET std::tr1::unordered_set - #define RCPP_UNORDERED_MAP std::tr1::unordered_map +#define RCPP_UNORDERED_SET std::unordered_set +#define RCPP_UNORDERED_MAP std::unordered_map - namespace std { - namespace tr1 { - template<> - struct hash { - std::size_t operator()(const Rcpp::String& key) const { - return pointer_hasher( key.get_sexp() ) ; - } - hash pointer_hasher ; - }; +namespace std { + template<> + struct hash { + std::size_t operator()(const Rcpp::String& key) const { + return pointer_hasher( key.get_sexp() ) ; } - } - - -#else - #define RCPP_UNORDERED_SET std::set - #define RCPP_UNORDERED_MAP std::map -#endif + hash pointer_hasher ; + }; +} #endif diff --git a/man/evalCpp.Rd b/man/evalCpp.Rd index d3285f6ad..78aedf7fc 100644 --- a/man/evalCpp.Rd +++ b/man/evalCpp.Rd @@ -5,16 +5,16 @@ Evaluate a C++ Expression } \description{ -Evaluates a C++ expression. This creates a C++ function using -\code{\link{cppFunction}} and calls it to get the result. +Evaluates a C++ expression. This creates a C++ function using +\code{\link{cppFunction}} and calls it to get the result. } \usage{ -evalCpp(code, depends = character(), plugins = character(), includes = character(), +evalCpp(code, depends = character(), plugins = character(), includes = character(), rebuild = FALSE, cacheDir = getOption("rcpp.cache.dir", tempdir()), showOutput = verbose, verbose = getOption("verbose")) -areMacrosDefined(names, depends = character(), includes = character(), - rebuild = FALSE, showOutput = verbose, +areMacrosDefined(names, depends = character(), includes = character(), + rebuild = FALSE, showOutput = verbose, verbose = getOption("verbose")) } \arguments{ @@ -47,10 +47,10 @@ see \code{\link{cppFunction}} } } \note{ - The result type of the C++ expression must be compatible with \code{Rcpp::wrap}. + The result type of the C++ expression must be compatible with \code{Rcpp::wrap}. } \value{ - The result of the evaluated C++ expression. + The result of the evaluated C++ expression. } \seealso{ \code{\link{sourceCpp}}, \code{\link{cppFunction}} @@ -58,10 +58,11 @@ see \code{\link{cppFunction}} \examples{ \dontrun{ -evalCpp( "__cplusplus" ) -evalCpp( "std::numeric_limits::max()" ) - -areMacrosDefined( c("__cplusplus", "HAS_TR1" ) ) +evalCpp("__cplusplus") +evalCpp("std::numeric_limits::max()") + +# areMacrosDefined is no longer exported by accessible via ':::' +Rcpp:::areMacrosDefined(c("__cplusplus", "GCC_VERSION")) } } diff --git a/src/api.cpp b/src/api.cpp index 62c1773f6..dbd02cd4d 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -171,32 +171,12 @@ SEXP as_character_externalptr(SEXP xp) { SEXP rcpp_capabilities() { Shield cap(Rf_allocVector(LGLSXP, 13)); Shield names(Rf_allocVector(STRSXP, 13)); - #ifdef HAS_VARIADIC_TEMPLATES - LOGICAL(cap)[0] = TRUE; - #else - LOGICAL(cap)[0] = FALSE; - #endif - #ifdef HAS_CXX0X_INITIALIZER_LIST - LOGICAL(cap)[1] = TRUE; - #else - LOGICAL(cap)[1] = FALSE; - #endif - /* exceptions are always supported */ - LOGICAL(cap)[2] = TRUE; - - #ifdef HAS_TR1_UNORDERED_MAP - LOGICAL(cap)[3] = TRUE; - #else - LOGICAL(cap)[3] = FALSE; - #endif - - #ifdef HAS_TR1_UNORDERED_SET - LOGICAL(cap)[4] = TRUE; - #else - LOGICAL(cap)[4] = FALSE; - #endif - - LOGICAL(cap)[5] = TRUE; + LOGICAL(cap)[0] = TRUE; // HAS_VARIADIC_TEMPLATES + LOGICAL(cap)[1] = TRUE; // HAS_CXX0X_INITIALIZER_LIST + LOGICAL(cap)[2] = TRUE; /* exceptions are always supported */ + LOGICAL(cap)[3] = TRUE; // HAS_TR1_UNORDERED_MAP + LOGICAL(cap)[4] = TRUE; // HAS_TR1_UNORDERED_SET + LOGICAL(cap)[5] = TRUE; // Modules (TODO respect header choice ?) #ifdef RCPP_HAS_DEMANGLING LOGICAL(cap)[6] = TRUE; @@ -204,7 +184,7 @@ SEXP rcpp_capabilities() { LOGICAL(cap)[6] = FALSE; #endif - LOGICAL(cap)[7] = FALSE; + LOGICAL(cap)[7] = FALSE; // Classic API #ifdef RCPP_HAS_LONG_LONG_TYPES LOGICAL(cap)[8] = TRUE; @@ -212,23 +192,9 @@ SEXP rcpp_capabilities() { LOGICAL(cap)[8] = FALSE; #endif - #ifdef HAS_CXX0X_UNORDERED_MAP - LOGICAL(cap)[9] = TRUE; - #else - LOGICAL(cap)[9] = FALSE; - #endif - - #ifdef HAS_CXX0X_UNORDERED_SET - LOGICAL(cap)[10] = TRUE; - #else - LOGICAL(cap)[10] = FALSE; - #endif - - #ifdef RCPP_USING_CXX11 - LOGICAL(cap)[11] = TRUE; - #else - LOGICAL(cap)[11] = FALSE; - #endif + LOGICAL(cap)[9] = TRUE; // HAS_CXX0X_UNORDERED_MAP + LOGICAL(cap)[10] = TRUE; // HAS_CXX0X_UNORDERED_SET + LOGICAL(cap)[11] = TRUE; // RCPP_USING_CXX11 #ifdef RCPP_NEW_DATE_DATETIME_VECTORS LOGICAL(cap)[12] = TRUE; From d4870afdc00d63c457ff43de69d7cbe1d8cef837 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 09:34:12 -0500 Subject: [PATCH 06/11] Reduced compiler.h to about a page of mostly defines and includes --- inst/include/Rcpp/platform/compiler.h | 121 +++----------------------- 1 file changed, 14 insertions(+), 107 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index 9162b717b..88c8012e1 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -22,132 +22,39 @@ // NB: A vast list valid identifiers is at these wiki pages: // http://sourceforge.net/p/predef/wiki/Home/ - -#undef GOOD_COMPILER_FOR_RCPP -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__) || defined(__INTEL_COMPILER) #define GOOD_COMPILER_FOR_RCPP -#endif -#ifdef __SUNPRO_CC -#define GOOD_COMPILER_FOR_RCPP -#endif -#ifdef __clang__ -#define GOOD_COMPILER_FOR_RCPP -#endif -#ifdef __INTEL_COMPILER -#define GOOD_COMPILER_FOR_RCPP -#endif - -#ifndef GOOD_COMPILER_FOR_RCPP -# error "This compiler is not supported" +#else +#error "This compiler is not supported" #endif +// New simpler test and minimal standard: C++11 or else we die #if __cplusplus < 201103L -# error "The C++ compilation standard is too old: use C++11 or newer." +#error "The C++ compilation standard is too old: use C++11 or newer." #endif #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif -// TODO: Clean in a subsequent round -#define RCPP_USING_CXX0X_OR_LATER - -// Check C++11 features (could/should work generally) -#if defined(__INTEL_COMPILER) - #define RCPP_USING_CXX11 - #if __INTEL_COMPILER >= 1210 - #define HAS_VARIADIC_TEMPLATES - #endif - #if __INTEL_COMPILER >= 1100 - #define HAS_STATIC_ASSERT - #endif -#elif defined(__clang__) - #define RCPP_USING_CXX11 - #if __has_feature(cxx_variadic_templates) - #define HAS_VARIADIC_TEMPLATES - #endif - #if __has_feature(cxx_static_assert) - #define HAS_STATIC_ASSERT - #endif -#elif defined(__GNUC__) - // given the check about __cplusplus we can unconditionally define - #define RCPP_USING_CXX11 - #define HAS_VARIADIC_TEMPLATES - #define HAS_STATIC_ASSERT -#endif - // C++11 features -- that used to be carefully tested for or worked around via CXX0X / TR1 +#define RCPP_USING_CXX11 +#define HAS_VARIADIC_TEMPLATES +#define HAS_STATIC_ASSERT #include #define HAS_CXX0X_UNORDERED_MAP #define HAS_CXX0X_UNORDERED_SET #define HAS_CXX0X_INITIALIZER_LIST - -// // Check TR1 Headers (TODO remove when no longer needed below) -// #if defined(__INTEL_COMPILER) || (defined(__GNUC__) && !defined(__clang__)) -// #define HAS_TR1_UNORDERED_MAP -// #define HAS_TR1_UNORDERED_SET -// #elif defined(__clang__) -// #if __has_include() -// #define HAS_TR1_UNORDERED_MAP -// #endif -// #if __has_include() -// #define HAS_TR1_UNORDERED_SET -// #endif -// #endif - -// #if defined(HAS_TR1_UNORDERED_MAP) && defined(HAS_TR1_UNORDERED_SET) -// #define HAS_TR1 -// #endif - -// Conditionally include headers -// #ifdef HAS_CXX0X_INITIALIZER_LIST #include -// #endif - -// // TODO: Simplify further: First case should work generally -// #ifdef RCPP_USING_CXX11 -// #if defined(HAS_CXX0X_UNORDERED_MAP) - #include - #define RCPP_USING_UNORDERED_MAP - #define RCPP_UNORDERED_MAP std::unordered_map - // #else - // #include - // #define RCPP_USING_MAP - // #define RCPP_UNORDERED_MAP std::map - // #endif - // #if defined(HAS_CXX0X_UNORDERED_SET) - #include - #define RCPP_USING_UNORDERED_SET - #define RCPP_UNORDERED_SET std::unordered_set - // #else - // #include - // #define RCPP_USING_SET - // #define RCPP_UNORDERED_SET std::set - // #endif -// #else -// #if defined(HAS_TR1_UNORDERED_MAP) -// #include -// #define RCPP_USING_TR1_UNORDERED_MAP -// #define RCPP_UNORDERED_MAP std::tr1::unordered_map -// // #else -// // #include -// // #define RCPP_USING_MAP -// // #define RCPP_UNORDERED_MAP std::map -// #endif -// #if defined(HAS_TR1_UNORDERED_SET) -// #include -// #define RCPP_USING_TR1_UNORDERED_SET -// #define RCPP_UNORDERED_SET std::tr1::unordered_set -// // #else -// // #include -// // #define RCPP_USING_SET -// // #define RCPP_UNORDERED_SET std::set -// #endif -// #endif +#include +#define RCPP_USING_UNORDERED_MAP +#define RCPP_UNORDERED_MAP std::unordered_map +#include +#define RCPP_USING_UNORDERED_SET +#define RCPP_UNORDERED_SET std::unordered_set #ifdef __GNUC__ #define RCPP_HAS_DEMANGLING #endif - #endif From 714c48348e85787ce86507abb960be0f43013532 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 09:56:32 -0500 Subject: [PATCH 07/11] Additional simplification, and typo fix --- inst/include/Rcpp/platform/compiler.h | 3 --- man/evalCpp.Rd | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index 88c8012e1..d49c4b5cc 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -42,9 +42,6 @@ #define HAS_VARIADIC_TEMPLATES #define HAS_STATIC_ASSERT #include -#define HAS_CXX0X_UNORDERED_MAP -#define HAS_CXX0X_UNORDERED_SET -#define HAS_CXX0X_INITIALIZER_LIST #include #include #define RCPP_USING_UNORDERED_MAP diff --git a/man/evalCpp.Rd b/man/evalCpp.Rd index 78aedf7fc..4dffb19e9 100644 --- a/man/evalCpp.Rd +++ b/man/evalCpp.Rd @@ -61,7 +61,7 @@ see \code{\link{cppFunction}} evalCpp("__cplusplus") evalCpp("std::numeric_limits::max()") -# areMacrosDefined is no longer exported by accessible via ':::' +# areMacrosDefined is no longer exported but accessible via ':::' Rcpp:::areMacrosDefined(c("__cplusplus", "GCC_VERSION")) } From 8809c39b0401fa7730f714394a256c1a6d10bb8a Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 10:11:29 -0500 Subject: [PATCH 08/11] Remove HAS_STATIC_ASSERT define and simplify at its sole use --- inst/include/Rcpp/internal/wrap.h | 20 +++++++------------- inst/include/Rcpp/platform/compiler.h | 1 - 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/inst/include/Rcpp/internal/wrap.h b/inst/include/Rcpp/internal/wrap.h index 50faa1d86..92ad009eb 100644 --- a/inst/include/Rcpp/internal/wrap.h +++ b/inst/include/Rcpp/internal/wrap.h @@ -522,18 +522,12 @@ namespace Rcpp { * quite a cryptic message */ template - inline SEXP wrap_dispatch_unknown_iterable(const T& object, ::Rcpp::traits::false_type) { - RCPP_DEBUG_1("wrap_dispatch_unknown_iterable<%s>(., false )", DEMANGLE(T)) - // here we know that T is not convertible to SEXP - #ifdef HAS_STATIC_ASSERT - static_assert(!sizeof(T), "cannot convert type to SEXP"); - #else - // leave the cryptic message - SEXP x = object; - return x; - #endif - return R_NilValue; // -Wall - } + inline SEXP wrap_dispatch_unknown_iterable(const T& object, ::Rcpp::traits::false_type) { + RCPP_DEBUG_1("wrap_dispatch_unknown_iterable<%s>(., false )", DEMANGLE(T)) + // here we know that T is not convertible to SEXP + static_assert(!sizeof(T), "cannot convert type to SEXP"); + return R_NilValue; // -Wall + } template inline SEXP wrap_dispatch_unknown_iterable__logical(const T& object, ::Rcpp::traits::true_type) { @@ -936,7 +930,7 @@ namespace Rcpp { if (v != NULL) return Rf_mkString(v); else - return R_NilValue; // #nocov + return R_NilValue; // #nocov } /** diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index d49c4b5cc..9c0176dc3 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -40,7 +40,6 @@ // C++11 features -- that used to be carefully tested for or worked around via CXX0X / TR1 #define RCPP_USING_CXX11 #define HAS_VARIADIC_TEMPLATES -#define HAS_STATIC_ASSERT #include #include #include From e1150dc57421d92c47322663bb073a6745cc2545 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Fri, 14 Mar 2025 13:19:09 -0500 Subject: [PATCH 09/11] Reflect code review comments --- inst/include/Rcpp/platform/compiler.h | 13 ++++--------- man/evalCpp.Rd | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/inst/include/Rcpp/platform/compiler.h b/inst/include/Rcpp/platform/compiler.h index 9c0176dc3..0248a9116 100644 --- a/inst/include/Rcpp/platform/compiler.h +++ b/inst/include/Rcpp/platform/compiler.h @@ -22,22 +22,17 @@ // NB: A vast list valid identifiers is at these wiki pages: // http://sourceforge.net/p/predef/wiki/Home/ -#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__clang__) || defined(__INTEL_COMPILER) -#define GOOD_COMPILER_FOR_RCPP -#else +#if !defined(__GNUC__) && !defined(__SUNPRO_CC) && !defined(__clang__) && !defined(__INTEL_COMPILER) #error "This compiler is not supported" #endif -// New simpler test and minimal standard: C++11 or else we die +// Simpler test and minimal standard: C++11 or else we die #if __cplusplus < 201103L #error "The C++ compilation standard is too old: use C++11 or newer." #endif -#ifdef __GNUC__ - #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - // C++11 features -- that used to be carefully tested for or worked around via CXX0X / TR1 +// These defines are all planned to get removed just how a number have already been removed. One at a time... #define RCPP_USING_CXX11 #define HAS_VARIADIC_TEMPLATES #include @@ -49,7 +44,7 @@ #define RCPP_USING_UNORDERED_SET #define RCPP_UNORDERED_SET std::unordered_set -#ifdef __GNUC__ +#if defined(__GNUC__) #define RCPP_HAS_DEMANGLING #endif diff --git a/man/evalCpp.Rd b/man/evalCpp.Rd index 4dffb19e9..49ce082e7 100644 --- a/man/evalCpp.Rd +++ b/man/evalCpp.Rd @@ -62,7 +62,7 @@ evalCpp("__cplusplus") evalCpp("std::numeric_limits::max()") # areMacrosDefined is no longer exported but accessible via ':::' -Rcpp:::areMacrosDefined(c("__cplusplus", "GCC_VERSION")) +Rcpp:::areMacrosDefined(c("__cplusplus", "RCPP_VERSION")) } } From 12c29eee6fcaf3bdd555067824aaa94a2dd3be7b Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Sat, 15 Mar 2025 23:47:44 -0500 Subject: [PATCH 10/11] Following rebase roll micro release and date, update ChangeLog --- ChangeLog | 16 ++++++++++++++++ DESCRIPTION | 4 ++-- inst/include/Rcpp/config.h | 4 ++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index af2bb1c3a..c7b2d6368 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2025-03-15 Dirk Eddelbuettel + + * DESCRIPTION (Version, Date): Roll micro version and date + * inst/include/Rcpp/config.h: Idem + + * inst/include/Rcpp/platform/compiler.h: Simplified and shortened + establishing C++11 as baseline; further PRs to complete this + * inst/include/Rcpp/String.h: Unconditionally use std::hash with C++11 + * inst/include/Rcpp/wrap.h: Unconditionally use static_assert + * inst/include/Rcpp/sugar/functions/sapply.h: Use std::result_of + (with C++11 or C++14) or std::invoke_result (C++17 or later) + * inst/include/Rcpp/sugar/functions/table.h: Use std::map + * inst/include/Rcpp/sugar/sets.h: Use std::unordered_{set,map} + * man/evalCpp.Rd: Update example + * src/api.cpp: Simplify rcpp_capabilities assignment + 2025-03-13 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll micro version and date diff --git a/DESCRIPTION b/DESCRIPTION index 0b6488a1d..c6707f3f2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: Rcpp Title: Seamless R and C++ Integration -Version: 1.0.14.6 -Date: 2025-03-13 +Version: 1.0.14.7 +Date: 2025-03-15 Authors@R: c(person("Dirk", "Eddelbuettel", role = c("aut", "cre"), email = "edd@debian.org", comment = c(ORCID = "0000-0001-6419-907X")), person("Romain", "Francois", role = "aut", diff --git a/inst/include/Rcpp/config.h b/inst/include/Rcpp/config.h index 639a46204..7c3288061 100644 --- a/inst/include/Rcpp/config.h +++ b/inst/include/Rcpp/config.h @@ -30,7 +30,7 @@ #define RCPP_VERSION_STRING "1.0.14" // the current source snapshot (using four components, if a fifth is used in DESCRIPTION we ignore it) -#define RCPP_DEV_VERSION RcppDevVersion(1,0,14,6) -#define RCPP_DEV_VERSION_STRING "1.0.14.6" +#define RCPP_DEV_VERSION RcppDevVersion(1,0,14,7) +#define RCPP_DEV_VERSION_STRING "1.0.14.7" #endif From fa5d1f11ff4db197509fe4ea7d61d58e363d7964 Mon Sep 17 00:00:00 2001 From: Dirk Eddelbuettel Date: Sun, 16 Mar 2025 09:49:19 -0500 Subject: [PATCH 11/11] Remove remaining stray HAS_CXX0X_INITIALIZER_LIST --- inst/include/Rcpp/vector/Vector.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/inst/include/Rcpp/vector/Vector.h b/inst/include/Rcpp/vector/Vector.h index bd9b5ba80..3feb8995c 100644 --- a/inst/include/Rcpp/vector/Vector.h +++ b/inst/include/Rcpp/vector/Vector.h @@ -236,11 +236,9 @@ class Vector : std::transform( first, last, begin(), func) ; } -#ifdef HAS_CXX0X_INITIALIZER_LIST Vector( std::initializer_list list ) { assign( list.begin() , list.end() ) ; } -#endif template Vector& operator=( const T& x) {