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 は実際には 2 つのテンプレート引数を取ることが示唆されます。私は今とても迷っています...)
私は次のようなことを考えました:
#ifdef __GLIBCXX__
# include <tr1/type_traits>
namespace __gnu_cxx = foo;
#else
# include <type_traits>
namespace std = foo;
#endif
... foo::enable_if< ... >
enable_if
ただし、テンプレートは1 つの名前空間で呼び出されますが、別の名前空間で呼び出されるため、これは機能しません__enable_if
。
この問題に対処したのは私が初めてではないと確信しています。誰かがこれを解決するための業界のベストプラクティスを教えてもらえますか? または、代わりにブーストを使用する必要がありますか?
同様の質問があります(私は思います)が、ここでは部分的な回答のみです。より良いオプションはありますか?
編集:私はこれを試しました<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 はドロップイン互換ではないようです。