boost — C ++, как обрабатывать пространства имен tr1 и non-tr1 в переносимом коде?

Есть ли канонический способ решения проблем с пространством имен, возникающих при попытке поддерживать переносимый код между цепочкой инструментов TR1 и не-TR1?

У меня есть проект VC ++ 2010, который #include <type_traits>, У меня также есть компилятор LLVM 3.0, который может справиться с этим хорошо. Это позволяет мне использовать шаблоны, такие как:

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

Однако мне также нужно собрать и поддерживать этот код на Clang-компиляторе 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

Этот компилятор, кажется, не имеет включаемого файла, вместо этого он имеет. Однако это вызывает у меня проблемы, потому что пространство имен изменилось с 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 на самом деле принимает два аргумента шаблона. Я сейчас очень растерялся …)

Я думал о том, чтобы сделать что-то вроде:

#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 вместо этого?

Есть похожий вопрос (я думаю), но только частичный ответ Вот. Есть ли лучшие варианты?

РЕДАКТИРОВАТЬ: я пробовал это, с <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 совместимы с раскрытием.

2

Решение

Я отвечу на свой вопрос, как я получил что-то рабочее, используя 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.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]