2013-02-12 55 views
2

有沒有一種規範的方法來處理嘗試在TR1和非TR1工具鏈之間維護便攜式代碼時出現的命名空間問題?C++如何處理可移植代碼中的tr1和非tr1命名空間?

我有一個VC++ 2010項目,#include <type_traits>。我也有一個LLVM 3.0編譯器,可以處理這個問題。這允許我使用的模板,例如:

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

但是我還需要在一個Xcode 4.5鐺編譯器構建並維護這些代碼:

$ /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 ::,這意味着我必須使用:

__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' 

因此,它似乎並不認爲性病:: enable_if和boost :: enable_if是插件兼容的。

+0

這個問題是一個後續從http://stackoverflow.com/questions/14821846 – meowsqueak 2013-02-12 01:21:15

+0

得到了一些與boost/type_traits.hpp工作 - 但請注意,需要使用boost :: enable_if_c作爲一個直接替換對於std :: enable_if - 或者顯然可以刪除尾部::值 - 請參閱「更多信息」,第2部分,http://www.gockelhut.com/c++/articles/has_member – meowsqueak 2013-02-12 01:36:32

+0

不幸的是,它在這裏擺動 - n-roundabouts - boost/type_traits.hpp包含is_complex.hpp,其中包括 - 不幸在此特定(精簡)編譯環境中不存在。嘎。通過包含而不是來解決這個問題 - 很高興Boost創建者將所有東西都分割得如此有用 - 方便。 – meowsqueak 2013-02-12 01:39:55

回答

1

我會回答我的問題,我沒有得到的東西用boost::enable_if_c工作(注意,下拉更換爲std::enable_ifboost::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。

+0

我在我自己的C++ 11後臺庫(比如(精確地)'enable_if')中做了什麼,只是在名稱空間'std'中實現(或'使用')所有東西。然後,如果我檢測到有一個tr1名稱空間(或者甚至不是,以防萬一),我打開它並將它用於名稱空間標準,以便對工具進行簡單的,向前兼容的訪問。這隻會留下諸如'hash <>'特化之類的東西的問題,這需要TR1工具本身在名稱空間「std」中實現。 – 2013-09-26 17:48:20

相關問題