Is there a canonical way to solve namespace problems that arise when trying to save portable code between TR1 and not TR1 toolchain?
I have a VC ++ 2010 project that #include <type_traits> . I also have an LLVM 3.0 compiler that can handle this fine. This allows me to use patterns, for example:
std::enable_if<typename> std::is_enum<typename>
However, I also need to build and maintain this code in the Xang Xerode 4.5 compiler:
$ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang --version Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn) Target: x86_64-apple-darwin11.4.2 Thread model: posix
This compiler does not have an include file, instead it has. However, this is causing me problems because the namespace has changed from std :: to __gnu_cxx ::, which means I have to use:
__gnu_cxx::__enable_if<typename>
Somehow I was able to determine that the definition of the __GLIBCXX__ symbol __GLIBCXX__ enough to determine whether I should use one or the other (not even sure if this is the right way to do this, but at the moment it works between compilers I use).
Therefore, I could resort to using preprocessor macros:
#ifdef __GLIBCXX__ # include <tr1/type_traits> # define ENABLE_IF __gnu_cxx::__enable_if #else # include <type_traits> # define ENABLE_IF std::enable_if #endif
But it looks like it might be a hack rather than the right solution. (Actually I tried this and it does not work, because trying to use __gnu_cxx::__enable_if causes this error:
error: too few template arguments for class template '__enable_if'
- further digging suggests that this version of enable_if actually takes two template arguments. I am very lost now ...)
I thought of doing something like:
#ifdef __GLIBCXX__ # include <tr1/type_traits> namespace __gnu_cxx = foo; #else # include <type_traits> namespace std = foo; #endif ... foo::enable_if< ... >
However, this does not work because the template is called enable_if in one namespace, but __enable_if in another.
I am sure that I am not the first person to deal with this problem - can someone point me to industry best practices to resolve this issue? Or should I just use Boost?
There is a similar question (I think), but only a partial answer here . Are there any better options?
EDIT: I tried this using <boost/type_traits.hpp> :
#include <boost/type_traits.hpp> template <typename ValueType> class Extractor <ValueType, typename boost::enable_if<boost::is_enum<ValueType>::value>::type> { public: ValueType extract(double value) { return static_cast<ValueType>(static_cast<int>(value)); // cast to int first, then enum, to satisfy VC++2010 } }; enum MyEnum { Enum0, Enum1 }; Extractor<MyEnum> e; MyEnum ev = e.extract(1.0);
However, this gives me the following compiler error in Xcode 4.5:
error: expected a qualified name after 'typename' class Extractor <ValueType, typename boost::enable_if<boost::is_enum<ValueType>::value>::type> { ^ error: unknown type name 'type'
So it looks like std :: enable_if and boost :: enable_if are not compatible.