C ++如何处理便携式code TR1和非TR1命名空间? [英] C++ how to handle tr1 and non-tr1 namespaces in portable code?
问题描述
有没有对付试图维持一个TR1和非TR1工具链之间移植code时出现的空间问题的正规途径?
Is there a canonical way to deal with the namespace issues that arise when trying to maintain portable code between a TR1 and non-TR1 toolchain?
我有一个VC ++ 2010项目的#include< type_traits>
。我也有一个LLVM编译器3.0能够处理这一优良。这让我使用的模板,例如:
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 templates such as:
std::enable_if<typename>
std::is_enum<typename>
不过,我还需要建设和维护该code上的X code ++ 4.5编译器铿锵:
However I also need to build and maintain this code on an Xcode 4.5 clang 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
该编译器似乎并不有一个包含文件,而不是它有一个。然而,这引起了我的问题,因为该命名空间已经从性病::改为__gnu_cxx ::,这意味着我必须使用:
This compiler doesn't seem to have a include file, instead it has a . However this is causing me problems because the namespace has changed from std:: to __gnu_cxx::, meaning I have to use:
__gnu_cxx::__enable_if<typename>
不知怎的,我能够确定该符号的定义 __ GLIBCXX __
足以确定我是否应该使用一个或另一个(甚至不知道这是向正确的方式做到这一点,但现在它的工作原理我使用的编译器)之间。
Somehow I was able to determine that the definition of the symbol __GLIBCXX__
is sufficient to determine whether I should use one or the other (not even sure that's the right way to do it, but for now it works between the compilers I'm using).
所以,我可以诉诸使用preprocessor宏:
So 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
但是,这似乎像它可能是一个更比黑客妥善解决的。 (其实我想这一点,这是行不通的,因为试图用 __ 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
中的其他
However this doesn't work because the template is called enable_if
in one namespace, but __enable_if
in the other.
我敢肯定,我没有处理这个问题的第一人 - 有人可以点我在行业的最佳实践解决这个吗?或者我应该只使用升压呢?
I'm sure I'm not the first person to deal with this problem - can someone point me at the industry best practice for resolving this please? Or should I just use Boost instead?
有一个类似的问题(我认为),但只是局部的答案 href=\"http://stackoverflow.com/a/7095608/143397\">。有没有更好的选择?
There is a similar question (I think) but only a partial answer here. Are there better options?
编辑:我想这一点,与&LT;升压/ type_traits.hpp&GT;
:
I tried this, with <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);
不过这给了我在下面的编译器错误X code ++ 4.5:
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'
所以它似乎并不认为性病:: enable_if和boost :: enable_if是插入式兼容。
So it doesn't seem that std::enable_if and boost::enable_if are drop-in compatible.
推荐答案
我会回答我的问题,我没有得到的东西用增压工作:: enable_if_c
(注该下拉更换为的std :: enable_if
是的boost :: enable_if_c
,而不是提高:: enable_if
)。
I'll answer my own question as I did get something working using boost::enable_if_c
(note that the drop-in replacement for std::enable_if
is 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
}
};
不过我还是很好奇,想知道是否有更好的方式来处理这不是诉诸提升。
However I'm still very curious to know whether there is a better way to deal with this than resorting to Boost.
这篇关于C ++如何处理便携式code TR1和非TR1命名空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!