Question

C++03 is lacking some things I'd love to use: std::shared_ptr, std::function and std::bind.

We can't fully switch to C++11, because the project needs to work with older libstdc++ versions. I know that this stuff is in Boost as well, but we cannot use that for other reasons.

Hence we started to use C++ 0x/TR1, which is supported by all the compiler versions we currently use. But we're having some trouble with it:

  • There's very little information about what of TR1 is implemented in which version of Clang/MSVC/GCC
  • I cannot figure out what the -std=c++0x switch does in Clang, compiles fine without it
  • I'm not sure what namespaces to use, e.g. std::tr1::shared_ptr vs std::shared_ptr

So, the question: Is C++ 0x/TR1 safe to use when portability matters? Is it implemented in all major compilers? Should I worry about proprietary toolchains etc.? Are we better off sticking to C++03?

Was it helpful?

Solution

TR1 is an experiment made by the C++ standards committee. The purpose of the experiment is to get field experience for libraries, with the hope of standardizing them in a future standard.

TR1 is not a normative standard.

The spec of TR1 specifies the use of namespace std::tr1. The reason things were not put into namespace std is to allow the committee more freedom in modifying the TR1 specification on the way to standardization. And yes, modifications were made in places when most of TR1 was standardized in C++11.

The TR1 document begins with these words:

This technical report is non-normative. Some of the library components in this technical report may be considered for standardization in a future version of C++, but they are not currently part of any C++ standard. Some of the components in this technical report may never be standardized, and others may be standardized in a substantially changed form.

The goal of this technical report it to build more widespread existing practice for an expanded C++ standard library. It gives advice on extensions to those vendors who wish to provide them.

Most, but not all of TR1, was widely implemented in in the 2005 time frame across gcc and MSVC. The llvm libc++ was developed after the TR1 time frame and was targeted straight at the new C++11 standard, which moves many TR1 components into namespace std, and makes them normative (required by a standard).

Clang is known to be used with both llvm libc++ and gcc's libstdc++.

I do not know which implementations of the std::lib you need to be portable among. If all of the places you need to port to implement TR1, it is safe, otherwise it is not. But TR1 is not a normative standard. C++98, C++03 and C++11 are normative standards.

Checked just for fun, and it turns out libcxx used in Emscripten is the issue, not Clang 3.2.

I have coached many, many project owners on how to make their code which uses TR1 portable across libstdc++ (has TR1) and libc++ (has C++11). libc++ places those TR1 components that were standardized into C++11 in namespace std as specified in C++11. It does this even when -std=c++03. This was done as a transition aid. libc++ does not try to be a C++03 conforming library. It's life starts with C++11.

libc++ has a version number macro called _LIBCPP_VERSION. If this macro is defined after include'ing a std-header, you are using libc++, else you are not. So you can write code like this:

#ifdef _LIBCPP_VERSION
// using libc++

#include <memory>
typedef std::shared_ptr<MyType> MyTypePtr;

#else  // !_LIBCPP_VERSION
// not using libc++

#include <tr1/memory>
typedef std::tr1::shared_ptr<MyType> MyTypePtr;

#endif  // _LIBCPP_VERSION

Note that you must have first included some std-header for _LIBCPP_VERSION to get defined or not. If you need to gratuitously include a std-header to see if _LIBCPP_VERSION gets defined, use:

#include <ciso646>  // detect std-lib

C++98/03/11 specify <ciso646> to do absolutely nothing. So it is very cheap to include. The libc++ implementation of this header does nothing but define _LIBCPP_VERSION.

Once done, your code can now easily switch among libc++ and other libraries which implement TR1.

OTHER TIPS

Instead of trying to make TR1 work on all your different compilers, I would just take the boost code (header-only) and copy-paste it into your own project (since you can't use boost directly for whatever reason). The boost versions are well supported and debugged, and will work consistently across any C++98 compiler that is supported by boost.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top