2013-02-12 2 views
2

TR1과 TR1이 아닌 도구 체인간에 이식 가능한 코드를 유지하려고 할 때 발생하는 네임 스페이스 문제를 해결할 표준 방법이 있습니까?C++ 휴대용 코드에서 tr1 및 non-tr1 네임 스페이스를 처리하는 방법?

저는 VC++ 2010 프로젝트 인 #include <type_traits>을 가지고 있습니다. 또한이 잘 처리 할 수있는 LLVM 3.0 컴파일러가 있습니다. 나는 또한 엑스 코드 4.5 연타 컴파일러에이 코드를 구축하고 유지하기 위해 필요하지만

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

: 포함

$ /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::__enable_if<typename> 

은 어떻게 든 내가 기호 __GLIBCXX__의 정의를 결정하는 데 충분하다고 판단 할 수 있었다 : 네임 스페이스가 :: __gnu_cxx하는 표준 : 변경된 때문에이 내가 의미 나에게 문제를 일으키는 것은 사용해야합니다 둘 중 하나를 사용할지 아니면 다른 하나를 사용해야하는지 (올바른 방법은 아니지만 지금은 사용중인 컴파일러간에 작동합니다).

그래서 나는 전처리 매크로를 사용에 의존 수 :

#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이 버전은 실제로 두 개의 템플릿 인수를하는 것이 지금 매우 잃었어요 제안 템플릿이 012,369,101라고 때문에이 작동하지 않습니다

    #ifdef __GLIBCXX__ 
    # include <tr1/type_traits> 
    namespace __gnu_cxx = foo; 
    #else 
    # include <type_traits> 
    namespace std = foo; 
    #endif 
    
    ... foo::enable_if<...> 
    

    : ...)

내가 좋아하는 일을 생각 한 네임 스페이스에이 있지만 다른 네임 스페이스에는 __enable_if입니다.

나는이 문제를 다루는 최초의 사람이 아니라고 확신합니다. 누군가 제발 업계의 우수 사례를 통해이를 해결해 주시겠습니까? 아니면 그냥 부스트를 사용해야합니까?

비슷한 질문이 있지만 (부분 생각은) 부분 응답 here입니다. 더 나은 옵션이 있습니까?

편집 : 나는 <boost/type_traits.hpp>와 함께,이 시도 : 그래서 그 표준 : enable_if을하지 않는 것

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' 

:

#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); 

그러나이 나에게 엑스 코드 4.5에서 다음과 같은 컴파일러 오류를 제공 boost :: enable_if는 드롭 인 호환입니다. 내가 boost::enable_if_c를 사용하여 작업 뭔가를 얻을처럼

+0

이 질문은 http://stackoverflow.com/questions/14821846 – meowsqueak

+0

의 후속 조치입니다. boost/type_traits.hpp와 작동하는 것을 얻었습니다. 그러나 boost-enable_if_c를 드롭 인 대체품으로 사용해야합니다. std :: enable_if에 대한 - 또는 분명히 후행 :: 값을 제거 할 수 있습니다 - 자세한 내용은 "추가 정보", 섹션 2, http://www.gockelhut.com/c++/articles/has_member – meowsqueak

+0

불행히도 그것은 스윙 n 회전 목마 여기에 - boost/type_traits.hpp에는 is_complex.hpp가 포함되어 있습니다. 여기에는 이 포함되어 있습니다.이 컴파일 (컷 다운) 환경에는 불행히도 존재하지 않습니다. 가. 가 아닌 를 포함하여이를 해결했습니다. Boost 제작자가 모든 것을 너무 유용하게 분할 해 주어서 기쁩니다. – meowsqueak

답변

1

내가 내 자신의 질문에 대답합니다 (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 
    } 
}; 

그러나 부스트를 사용하는 것보다이 문제를 해결할 더 좋은 방법이 있는지 아직도 궁금합니다.

+0

C++ 11 백 포트 라이브러리 (정확히 말하면'enable_if ')는 네임 스페이스'std'에서 모든 것을 구현 (또는'사용')하는 것이 었습니다. 그런 다음 tr1 네임 스페이스가 발견되면 (또는 그렇지 않은 경우에도 마찬가지입니다.) 도구에 대한 쉽고 포워드 호환 액세스가 가능하도록 네임 스페이스 표준으로 열어 '사용'합니다. 이것은'hash <>'전문화와 같은 문제의 문제를 남겨 둡니다. TR1 도구 자체가 네임 스페이스'std'에 구현되어야합니다. –

관련 문제