C ++如何在可移植代码中处理tr1和非tr1命名空间?

时间:2013-02-12 01:02:36

标签: c++ boost namespaces tr1 typetraits

是否有规范的方法来处理在尝试在TR1和非TR1工具链之间维护可移植代码时出现的命名空间问题?

我有一个#include <type_traits>的VC ++ 2010项目。我还有一个LLVM 3.0编译器,可以处理这个问题。这允许我使用以下模板:

std::enable_if<typename>
std::is_enum<typename>

但是我还需要在Xcode 4.5 clang编译器上构建和维护这段代码:

$ /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

这个编译器似乎没有包含文件,而是有一个。然而,这导致我的问题,因为命名空间已从std ::更改为__gnu_cxx ::,这意味着我必须使用:

__gnu_cxx::__enable_if<typename>

不知怎的,我能够确定符号__GLIBCXX__的定义足以确定我是否应该使用其中一个(甚至不确定这是否正确的方法),但现在它可以在我正在使用的编译器。

所以我可以使用预处理器宏:

#ifdef __GLIBCXX__
# include <tr1/type_traits>
# define ENABLE_IF __gnu_cxx::__enable_if
#else
# include <type_traits>
# define ENABLE_IF std::enable_if
#endif

但这似乎更像是一个黑客而不是一个正确的解决方案。 (实际上我尝试了这个并且它不起作用,因为尝试使用__gnu_cxx::__enable_if会导致此错误:

error: too few template arguments for class template '__enable_if'
  • 进一步挖掘表明此版本的enable_if实际上需要两个模板参数。我现在很迷茫......)

我想做类似的事情:

#ifdef __GLIBCXX__
# include <tr1/type_traits>
namespace __gnu_cxx = foo; 
#else
# include <type_traits>
namespace std = foo;
#endif

... foo::enable_if< ... >

但是这不起作用,因为模板在一个名称空间中被称为enable_if,而在另一个名称空间中被称为__enable_if

我确信我不是第一个处理这个问题的人 - 有人能指出行业最佳实践来解决这个问题吗?或者我应该只使用Boost?

有一个类似的问题(我认为),但只有部分答案here。有更好的选择吗?

编辑:我尝试了<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);

然而,这在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'

所以似乎std :: enable_if和boost :: enable_if似乎不兼容。

1 个答案:

答案 0 :(得分:1)

我会回答我自己的问题,因为我确实使用boost::enable_if_c了解了一些问题(请注意std::enable_if的替代品是boost::enable_if_c,而不是boost::enable_if

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_enum.hpp>

// this would work except one of my environments doesn't contain <complex> so it's
// too inclusive. Better (for me) to use the more specific includes above.
// #include <boost/type_traits.hpp>  

template <typename ValueType>
class Extractor <ValueType, typename boost::enable_if_c<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
  }
};

然而,我仍然很想知道是否有更好的方法来解决这个问题,而不是诉诸Boost。