Using Rcpp with C++11, C++14 and C++17

February 18, 2017
By

(This article was first published on Rcpp Gallery, and kindly contributed to R-bloggers)

Background

When we started the Rcpp Gallery in late 2012, a few of us spent the next four weeks diligently
writing articles ensuring that at least one new article would be posted per day. Two early articles
covered the then-budding support for C++11. Both
First steps in using C++11 with Rcpp and
A first lambda function with C++11 and Rcpp
started by actually showing how to set the compiler directive via the PKG_CXXFLAGS environment
variable.

Both posts were updated a few months later to demonstrate the C++11 plugin that was added in Rcpp
release 0.10.3 in March of 2013, or almost four years ago. Many posts here, on
StackOverflow and of course on the mailing list
make use of the plugin to tell the compiler to turn on C++11 support. In the early days, this often
meant partial support via (in the case of g++) the -std=c++0x switch. This is still
supported by Rcpp
as in particular the Windows side of things was relying on older compilers like g++ version 4.6.*
until more recently (see below).

But some things got a lot better with R 3.1.0. As the
NEWS announcement dryly noted: There
is support for compiling C++11 code in packages on suitable platforms: see ‘Writing R Extensions’.

which was coupled with support for selecting the C++11 language standard via either CXX_STD in
src/Makevars, or the SystemRequirements line in DESCRIPTION. In late 2011, Martyn Plummer also
wrote a helpful
R Journal article on
best practices for portable C++ packages.

And as we alluded to above, Rcpp has supported C++11 since the dawn of time (because, as we detail
below, it ultimately comes down what your compiler supports, and what R facilitates). Many CRAN
packages have by now taken advantage of this increased support for C++11 in particular. As of
today, we see 88 CRAN packages declaring this via DESCRIPTION and 127 CRAN package via
src/Makevars. And of course, almost all use Rcpp along with C++ to take advantage of the R and
C++ integration it offers.

Rcpp: Sitting between your Compiler and R

So what are the defining parameters for support by Rcpp? In essence, Rcpp is guided by just two
(external) factors:

  • the support in the provided compiler, and

  • the support offered by R for package building,

and both are worth detailing as we do in the next two sections..

Compiler Support

First, the choice of compiler matters. Rcpp operates on top of R, and (like any R package) it is
driven entirely by the build instructions from R. It can therefore be dependent on the compiler
choices offered by R. This meant g++ version 4.6.3 for Windows for years. And this got a lot
better when Rtools switched to g++ version 4.9.3 with R 3.3.0 not quite a year ago. It now means
that support for C++11 is almost universal. (Some small things are still missing in g++-4.9.3;
notably complete support for the C++ Standard Library leading us recently to
backport get_time from LLVM into RcppCCTZ. Also
note that macOS / OS X has its own dependency chain due to compiler, and release, choices made by
the R package build system for that platform.)

Now, that is just the minimum available compiler for a particular platform, albeit a very important
one as it defines what binary CRAN packages on Windows can support. Other platforms, however,
have a faster release cadence. g++-5 and clang++-3.3 are now fairly common and have
(near-)complete C++11 support. The most recent Ubuntu release 16.10 even defaults to g++ version
6.2.0, and Debian already has version 6.3.0 (and binaries of version 7.* in its experimental
branch). Similarly, recent version of clang are available both directly in the distributoin and via
nightly builds from dedicated PPAs.

And for these ‘6.*’ version of g++, the default C++ standard is already C++14, the follow-up
standard release to C++11. For example, C++14 extends support for auto to return values so that
we can compile a simple program such as

#include 

auto doubleMe(const int & x) {
    return x+x;
}

int main(void) {
    std::cout << "1.0         -> " << doubleMe(1.0) << "\n"
              << "1           -> " << doubleMe(1)   << "\n"
              << std::endl;
}

withour any additional switches or flags if the compiler is as recent as g++ version 6. A plain
g++ -o demoprog demoprog.cpp will do (provided the snippet was saved as file demoprogr.cpp) as
C++14 is the default for this compiler. Otherwise, adding -std=c++14 explicitly instruct the
compiler to compile as C++14.

Moreover, it also works for R:

Rcpp::cppFunction("auto doubleMe(const int &x) { return x + x; }")
doubleMe(1L)
[1] 2
doubleMe(1)
[1] 2

(on a machine such as the one used to write this piece) without requiring any additional plugins.
As a reminder, cppFunction() supports these via the plugin= argument. On another machine, we
might use Rcpp::cppFunction("auto doubleMe(const int &x) { return x + x; }", plugin="cpp14").
Similarly, in code sourced via sourceCpp() we would use an attribute; see the
Rcpp Attributes vignette
for details.

Support by R for Packages: C++14 coming soon via R-devel

As noted above, the R 3.1.0 release started to add support for modern C++ by enabling packages to
select C++11.

The next release will be R 3.4.0. While as of now without an announced release date, it is likely to
be shipped this April. It will bring support for C++14. The current draft of its version of
Writing R Extenions shows that CXX_STD = CXX14 can be used to select this language standard in a
package. Several build variables extend support to CXX1Y beyond the existing CXX1X, see the
Writing R Extenions manual for full details.

To illustrate, on a machine with g++ version 6.*, nothing has to be turned on for C++14 in what
will be R 3.4.0.

[email protected]:~$ grep "^CXX/*STD" /usr/local/lib/R-devel/lib/R/etc/Makeconf 
CXX98STD = -std=gnu++98
CXX1XSTD = -std=gnu++11
CXX1YSTD = 
[email protected]:~$ 

On a machine where g++-5 is the default, the CXX1XSTD value may be empty as this compiler
defaults to C++11; we would expect CXX1YSTD = -std=c++14 there (or the ‘gnu’ variant).

As we noted above, well over one-hundred packages on CRAN already use C++11. We expect to see C++14
being used once R 3.4.0 is released later this spring

Extensions on the Rcpp side: C++17

As we wrote in the opening paragraph, a plugin for C++11 has been part of Rcpp for several years.
And a plugin for C++14 was added by Dan in Rcpp 0.12.4 about a year ago.

The current development sources of Rcpp, corresponding to interim GitHub release 0.12.9.3, added a
plugin for C++17 as experimental support exists in g++ and clang++ right now. With that, a suitably
recent compiler, and a version of Rcpp that is at least release 0.12.9.3, the following example
(motivated by this example section of the
C++ Standard post) also
builds:

#include 

// [[Rcpp::plugins(cpp17)]]                                        

// [[Rcpp::export]]
void useAny() {
    std::experimental::any x(5);
    // some more here ...
    x = "cat";
}

Summary

This note discussed where Rcpp stands with respect to “modern C++”. As a brief summary:

  • Rcpp supports any C++ language standard the underlying compiler supports: C++98, C++11, C++14,
    C++17;

  • Packages using Rcpp can deploy every language standard suppported by R: currently C++, C++11 and
    very soon C++14;

  • Package distribution may need to reflect the build infracture; on Windows this means g++-4.9.3
    with near-complete C++11 support;

  • Local developement can be more experimental and even C++17 is now supported by Rcpp as well;

  • Portable packages should specify the C++ language standard they expect (unless it is C++98).

To leave a comment for the author, please follow the link and comment on their blog: Rcpp Gallery.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Sponsors

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)