[Rcpp-devel] Patch for using Rcpp with proper check of TR1/C++11 headers

Yan Zhou zhouyan at me.com
Mon Dec 3 07:11:51 CET 2012


Hi Dirk,

Here is a more detailed summary of the change and some test results

Things affected by the change
=============================

* The use of <initializer_list>, <unordered_map> and <unordered_set> header
* The use C++11 static assert and variadic template

Things work before the change
=============================

GCC, Clang, Intel, SunPro in C++98 mode
TR1 headers are used if some macros defined, otherwise ordered map and set are
used.

Earlier GCC in C++0x mode (up to version 4.6 series)

Things do not work before the change
====================================

Any compiler with __cplusplus >= 201103L, Clang, Intel, GCC 4.7 with -std=c++0x
This is due to the fact that Rcpp/sugar/sets.h has the following code

#if __cplusplus >= 201103L
    #define RCPP_UNORDERED_SET std::unordered_set
    #define RCPP_UNORDERED_MAP std::unordered_map
#elif defined(HAS_TR1_UNORDERED_SET)
    #define RCPP_UNORDERED_SET std::tr1::unordered_set
    #define RCPP_UNORDERED_MAP std::tr1::unordered_map
#else
    #define RCPP_UNORDERED_SET std::set
    #define RCPP_UNORDERED_MAP std::map
#endif

while C++11 <unordered_map> and <unordered_set> are not included anywhere

Clang with libc++
Similar reasons. libc++ does not provide TR1 headers but only C++98 and C++11
headers

The change
==========

If the compiler is in a C++0x/11 mode, (-std=c++0x, or -std=c++11), then choose
<unordered_map> and <unordered_set> if possible. Otherwise choose <map> and
<set>

If the compiler is in a C++98 mode, (usually the default), then choose
<tr1/unordered_map> and <tr1/unordered_set> if possible. Otherwise choose <map>
and <set>

We do not try to choose TR1 headers in C++11 mode. Some testing shows very
wired errors in this combinations when using intel compilers.

However, the GCC is an exception. Even when in C++11 mode, GCC will always try
to use TR1 headers instead of C++11 headers. This is for backward
compatibility, to void breaking of ABI. If this is not desired, remove the
comment before #define HAS_CXX0X_FLAG in the following (line 107)

...
#elif defined(__GNUC__)
    #ifdef __GXX_EXPERIMENTAL_CXX0X__
        // #define HAS_CXX0X_FLAG
        #if GCC_VERSION >= 40300
            // #define HAS_VARIADIC_TEMPLATES
            #define HAS_STATIC_ASSERT
        #endif
    #endif
#endif
...

C++11 static assert feature is properly tested for the four
GOOD_COMPILER_FOR_RCPP.

C++11 variadic templates are disabled for all compilers. This clearly does not
affect C++98 implementation. In C++11 mode, when this feature is enabled, my
test results showed some wired error emitted from basename, which was called by
sourceCppContext. This may need some further investigation. I believe this is
not due to the change made here. The compilers I tried was Intel icpc 13, GCC
4.6 and 4.7. They all have the same problem when variadic templates are
enabled.

C++11 <initializer_list> is also properly tested for each of the four compilers

A small glitch in Rcpp/traits/comparator_type.h is fixed. This is found when
running the Unit tests with Clang, which somehow is more strict than GCC.

Things work the same way before AND after the change
=====================================================

The four compilers in C++98 mode
The ABI shall be unchanged for these situations. At least this is the
intention, everything depend on Rcpp shall not need to be rebuilt. But maybe
some carelessness invalidate this claim. More testing on this front are needed.

Things break before still break anyway.

Things work after the change BUT not before
===========================================

Clang with libc++ in C++98 and C++11 mode, -std=c++98 or -std=c++0x;
-stdlib=libc++

Intel icpc in C++11 mode, -std=c++0x

GCC 4.7 in C++11 mode, -std=c++0x

Compilers tested
================

The following are compilers tested, within each paragraph, the first line is
compiler version and platform. The second and third lines are the C and C++
compilers and flags used when building R. The R configure script may add
additional flags like -std=gnu99. Building R only uses the C compiler and C
flags. However the configure script capture the C++ compiler and flags for use
when, e.g., R CMD INSTALL Rcpp

All tests are peformed with R 2.15.2 patched

Mac OS X Mountain Lion 10.8.2, Xcode 4.5.2, clang 4.1 (based on LLVM 3.1svn)
clang
clang++ -std=c++98 -stdlib=libc++

Mac OS X Mountain Lion 10.8.2, Xcode 4.5.2, clang 4.1 (based on LLVM 3.1svn)
clang
clang++ -std=c++11 -stdlib=libc++

Mac OS X Mountain Lion 10.8.2, Xcode 4.5.2, clang 4.1 (based on LLVM 3.1svn)
clang
clang++ -std=c++98 -stdlib=libstdc++

Mac OS X Mountain Lion 10.8.2, Xcode 4.5.2, clang 4.1 (based on LLVM 3.1svn)
clang
clang++ -std=c++11 -stdlib=libstdc++

The official build of R on Mac OS X use GCC 4.2.1 on Mac OS X Leopard, which is
a legacy system I don't have access any more.

Ubuntu 12.10 Intel C++ 13.0.1
icc -std=gnu99 -gcc-name=gcc-4.7 -fp-model strict
icpc -std=c++98 -gcc-name=gcc-4.7 -gxx-name=g++-4.7 -fp-model strict

Ubuntu 12.10 Intel C++ 13.0.1
icc -std=gnu99 -gcc-name=gcc-4.7 -fp-model strict
icpc -std=c++11 -gcc-name=gcc-4.7 -gxx-name=g++-4.7 -fp-model strict

Ubuntu 12.10 GCC 4.7.2
gcc
g++ -std=c++98

Ubuntu 12.10 GCC 4.7.2
gcc
g++ -std=c++11

Test results
============

Rcpp Unit Test
--------------

The following are the Rcpp Unit Test results for the tested compilers above.
The links are named as platform-C++Compiler-std=Lang.html

http://www.yan-zhou.com/rcppunit/mac-clang++-std=c++98-stdlib=libstdc++.html
http://www.yan-zhou.com/rcppunit/mac-clang++-std=c++98-stdlib=libc++.html
http://www.yan-zhou.com/rcppunit/mac-clang++-std=c++11-stdlib=libstdc++.html
http://www.yan-zhou.com/rcppunit/mac-clang++-std=c++11-stdlib=libc++.html
http://www.yan-zhou.com/rcppunit/linux-icpc-std=c++98.html
http://www.yan-zhou.com/rcppunit/linux-icpc-std=c++11.html
http://www.yan-zhou.com/rcppunit/linux-g++-std=c++98.html
http://www.yan-zhou.com/rcppunit/linux-g++-std=c++11.html

As shown in those pages, most compilers works well. With Intel Compiler and
Clang with libc++, in C++11 mode, two tests fails. These may need some further
investigation. It could be problems with compiler or the code in Rcpp. Either
way, since these compilers do no work at all previously, I consider this a
improvement.

Rcpp and RInside examples
-------------------------

These all works well without any problem as far as I can tell

Packages distributed in Rcpp SVN repository
-------------------------------------------

RcppCImg, RcppModels cannot compile due to some C++ issues. I believe they are
not due to the changes as the same error happens when using GCC and a SVN
version of Rcpp without the changes. RcppParDE has some dependencies I cannot
find.

When using Clang on Mac OS X without libc++ but using -std=c++11, RcppEigen and
RcppArmadillo failed to build. However those are due the two libraries made
some wrong assumption about the existence of some C++11 headers. With clang
-std=c++11-stdlib=libstdc++ on Mac OS X, __cplusplus test will give the wrong
impression that C++11 is supported, while the libstdc++ on Mac OS X is still
the GCC 4.2.1 version, which does not have any C++11 support. These issues
shall be fixed in the upstream projects rather than within Rcpp.

Other packages build successfully and examples work well.

Packages depend on Rcpp
-----------------------

There are about 90 such packages. Most of them built well. But more tests are
needed.

Best,

Yan Zhou
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20121203/cafe8fda/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Rcpp.diff
Type: text/x-patch
Size: 11202 bytes
Desc: not available
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20121203/cafe8fda/attachment-0001.bin>


More information about the Rcpp-devel mailing list