C ++ 11 (즉, -std=c++11
)에서 라이브러리를 테스트하고 있습니다. 라이브러리는 auto_ptr
및 다음 패턴을 사용합니다.
Foo* GetFoo() { autoptr<Foo> ptr(new Foo); // Initialize Foo ptr->Initialize(...); // Now configure remaining attributes ptr->SomeSetting(...); return ptr.release(); }
C ++ 11 지원 중단 auto_ptr
, 그래서 우리는 그것에서 벗어나고 싶습니다.
그러나 코드는 C ++ 03과 C ++ 11을 모두 지원하므로 홱 잡아 당기는 것처럼 간단하지 않습니다. auto_ptr
. 라이브러리에 외부 종속성이 없다는 점도 언급 할 가치가 있습니다. C ++ 03을 사용하고 Autotools, Cmake, Boost, …를 사용하지 않습니다.
이동을 위해 디자인 변경을 어떻게 처리해야합니까? C ++ 03과의 호환성을 유지하면서 C ++ 11 용 auto_ptr
에서?
댓글
6 개 또는 12 개의 다른 생성자가 없습니다. (이 시점에서 내가 한 일은 POD 유형의 멤버 변수가 C ++ 생성자에서 정상적인 기본값으로 초기화되었는지 확인했습니다.)
Answer
대부분의 측면에서 std::unique_ptr
가 드롭되도록 만들어졌습니다. (하지만 더 안전한) std::auto_ptr
를 대체하므로 코드 변경이 필요한 경우 외에는 거의 필요하지 않습니다. (요청하신대로) unique_ptr
또는 auto_ptr
를 사용하도록 코드에 지시합니다.
몇 가지 방법이 있습니다. 이것 (그리고 각각은 자체 목록 장단점이 있습니다). 제공된 코드 샘플이 주어지면 처음 두 옵션 중 하나를 선호합니다 .
옵션 1
#if __cplusplus >= 201103L template <typename T> using auto_ptr = std::unique_ptr<T>; #else using std::auto_ptr; #endif
Tradeoffs;
- 전역 네임 스페이스에
auto_ptr
이름을 도입합니다. ; 자신의 " 비공개 " 네임 스페이스 - C ++ 17로 마이그레이션 한 후 (
auto_ptr
는 완전히 제거 될 것입니다.) 더 쉽게 검색하고 바꿀 수 있습니다.
를 정의하여이를 완화 할 수 있습니다.
옵션 2
template <typename T> struct my_ptr { #if __cplusplus >= 201103L typedef std::unique_ptr<T> ptr; #else typedef std::auto_ptr<T> ptr; #endif };
트레이드 오프;
- 아마도 작업하기가 더 번거 롭습니다. 현재의 모든
auto_ptr
코드를 다음과 같이 변경해야합니다.my_ptr<T>::ptr
- 이름이 글로벌 네임 스페이스에 도입되지 않는 더 나은 안전성
와 같은 것
옵션 3
다소 논란의 여지가 있지만 std
클래스를 기본으로 사용하는 것에 대한주의 사항을 참을 준비가되어 있다면
#if __cplusplus >= 201103L template <typename T> using my_ptr = std::unique_ptr<T>; #else template <typename T> class my_ptr : public std::auto_ptr<T> { // implement the constructors for easier use // in particular explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {} }; #endif
Tradeoffs;
- 가상 기반 (특히 비가 상 소멸자)이 예상되는 상속 된 클래스를 사용하려고하지 마십시오. 케이스에 문제가 있지만주의해야합니다.
- 다시, 코드 변경
- 잠재적 인 네임 스페이스 불일치-모두 포인터 클래스를 사용하여 시작하는 방법에 따라 다릅니다.
옵션 4
포인터를 새 클래스로 래핑하고 필요한 함수를 멤버에 집계
template <typename T> class my_ptr { // could even use auto_ptr name? #if __cplusplus >= 201103L std::unique_ptr<T> ptr_; #else std::auto_ptr<T> ptr_; #endif // implement functions required... T* release() { return ptr_.release(); } };
Tradeoffs;
- A 실제로 원하는 것은 구현을 " " 교체
댓글
- 정답입니다. 나는 실제로 그것을 약간 조사했고, 당신은 내가 시도한 테스트 중 적어도 세 번을 맞았습니다. (당신이 부족한 것은 OS X 및 Clang 특정 항목입니다. OS X는 여전히 C ++ 03 용 TR1 네임 스페이스를 사용하기 때문에 곰이며 다음 방법을 사용하여 항목을 포함해야합니다. 네임 스페이스 ' std iv id에 ' unique_ptr '라는 이름이 없습니다. LLVM / Clang에서 컴파일하는 경우 = “3e89994714″>
).
tr1
네임 스페이스 이외의 ++ 03 / 11 믹스가 더 이상 존재하지 않습니다 (libstdc ++가 아닌 libc ++를 사용합니다).tr1이 비 규범 적이라는 것을 알고 있지만 ' 초안 (여기) 에서 파일은 <tr1/...>
이어야합니다. 실제로 <memory>
헤더에있는 것만 언급합니다. 12c784e8c1 “> 네임 스페이스.
CXX=...
를 지정하거나 부족할 때 암시 적으로 선택합니다.) c++ -v -std=c++11 -x c++ - < /dev/null
. 덤프 된 포함 디렉토리를 grep'd
, 포함하지 않습니다 unique_ptr
. 답변
옵션 5 : 직접 별칭.
#if __cplusplus >= 201103L template<typename T> using MyPtr = std::unique_ptr<T>; #else #define MyPtr std::auto_ptr #endif
장단점 :
-
최신 언어 버전 인 AKA C ++ 11 이상의 경우 별칭 유형이 올바른 스마트 포인터에 매핑됩니다. 실제로 std :: auto_ptr에 특정한 API에 의존하는 모든 사용자 코드는 컴파일러에 의해 플래그가 지정되며, 이는 이것이 실제로 수정 될 것이라는 궁극적 인 보장입니다.
-
레거시에서 C ++ 03 모드 유형 별칭은 매크로입니다. 이것은 총체적이지만 결과 구문
MyPtr<T>
는 나머지 코드 전체에서 C ++ 11 케이스와 동일합니다. -
이를 설정하려면 모든 auto_ptr 변수를 찾아
MyPtr
로 변경해야합니다.
댓글
- ' 이것이 무엇을 참조하고 있는지 매우 불분명합니다 (그리고 ' 전혀 질문이 아닙니다).
- @autophage 답변이라고 생각합니다 … 그래서 아마도 질문이 아닐 것입니다.
auto_ptr
범위가 지정되어 있습니까 (예 :std::auto_ptr
), 스마트 포인터가 다른 네임 스페이스 여야합니까 아니면 가져올 수 있습니까?Foo::Initialize
를Foo::Foo
로 접을 수 있습니다.