是否有规范的方法来处理在尝试在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'
我想做类似的事情:
#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似乎不兼容。
答案 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。