2

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

我有一个 VC++2010 项目#include <type_traits>。我还有一个 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 代替?

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

编辑:我试过这个,用<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 似乎不兼容。

4

1 回答 1

1

我会回答我自己的问题,因为我确实使用了一些东西boost::enable_if_c(请注意,替换为std::enable_ifis boost::enable_if_c, not 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 更好的方法来处理这个问题。

于 2013-02-12T01:47:40.600 回答