C ++如何处理便携式code TR1和非TR1命名空间? [英] C++ how to handle tr1 and non-tr1 namespaces in portable code?

查看:97
本文介绍了C ++如何处理便携式code TR1和非TR1命名空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有对付试图维持一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆