C ++ 11에서 auto_ptr 지원 중단에 대한 디자인 변경을 처리하는 방법은 무엇입니까?


12

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을 모두 지원하므로 yanking처럼 간단하지 않습니다 auto_ptr. 또한 라이브러리에 외부 종속성이 없다는 것을 언급 할 가치가 있습니다. C ++ 03을 사용합니다. Autotools, Cmake, Boost 등을 사용하지 않습니다.

auto_ptrC ++ 03과의 호환성을 유지하면서 C ++ 11 에서 벗어나기 위해 디자인 변경을 어떻게 처리해야 합니까?


의 모든 있습니까 auto_ptr스코프 (예 std::auto_ptr), 그들이해야하거나 스마트 포인터가 다른 네임 스페이스에서 얻을 수 있습니까?
Niall

여담으로, 당신은 접을 할 수 있습니다 Foo::InitializeFoo::Foo.
MSalters

1
@MSalters-예, 그것은 항상 내가 불편하게 느낀 것들 중 하나였습니다. 라이브러리는 1990 년대에 디자인되었으며 디자인이 MFC와 유사 하다고 생각 합니다. 즉, 낮은 수준의 C ++ 구성과 "높은 수준의"개체 구성이있었습니다. 이 기능은 트레이드 오프로 사용되었으므로 클래스에는 6 또는 12 개의 다른 생성자가 없습니다. (이 시점에서 내가 한 일은 POD 유형의 멤버 변수가 C ++ 생성자에서 기본값으로 초기화되도록 보장하는 것입니다.)

답변:


13

대부분의 경우 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

트레이드 오프;

  • 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

트레이드 오프;

  • 가상 기반 (특히 비 가상적 소멸자 포함)이 예상되는 상속 된 클래스를 사용하지 마십시오. 이 경우에 문제가되지는 않지만 알고 있어야합니다.
  • 다시, 코드 변경
  • 잠재적 인 네임 스페이스 불일치-모두 포인터 클래스를 사용하여 시작하는 방법에 따라 다릅니다.

옵션 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(); }
};

트레이드 오프;

  • 당신이 정말로 원하는 모든 것은 구현을 "스왑"하는 것입니다.

아주 좋은 대답입니다. 나는 실제로 그것을 조금 연구했고, 당신은 내가 시도한 테스트 중 적어도 세 가지를 맞았습니다. (당신이 부족한 것은 OS X와 ​​Clang에 관한 것입니다. OS X는 때때로 C ++ 03에 TR1 네임 스페이스를 사용하기 때문에 곰입니다.이 방법을 사용하여 항목을 포함해야합니다 : 네임 스페이스에 'unique_ptr'이라는 유형 없음 LLVM / Clang에서 컴파일 할 때 'std' ).

@jww. OS X (XCode 6.4 및 Apple LLVM 버전 6.1.0 (clang-602.0.53) (LLVM 3.6.0svn 기반))에 있으며 tr1네임 스페이스 이외의 C ++ 03/11 믹스에 문제가 없습니다. 더 이상 거기에 있습니다 (libstdc ++가 아닌 libc ++을 사용합니다). 나는 tr1이 비 규범 적이라는 것을 알고 있지만, 초안 (여기) 에서 파일이 <tr1/...>전혀 있어야한다는 곳을 찾을 수는 없습니다. 실제로는 네임 스페이스 에있는 헤더 <memory>등의 파일 에 있다고 언급 tr1합니다.
Niall

@jww. 컴파일러, 라이브러리 및 대상 장치의 특정 조합이 주어지면 몇 가지 추가 스탠드를 수행해야 할 수도 있습니다. 그렇지 않으면 OS X에서 clang 및 libc ++로 이동하는 것을 고려하십시오. 솔직히 나는 libc ++가 OS X에 대한 새로운 "네이티브"C ++ 라이브러리라고 생각합니다. 기본값은 그 것입니다. clang / Apple 관계의 역사와 OS X의 GCC 도구가 오래되었거나 (라이브러리) 제거 된 것 (GCC가 어쨌든 clang에 대한 스텁이라고 알고있는 한) 이외의 다른 주장을 뒷받침 할 방법이 없습니다. ).
Niall

"그렇지 않으면, OS X에서는 clang과 libc ++로 옮기는 것을 고려하십시오 ..." -네, 동의합니다. 그러나 사용자가 그러한 선택을하도록 강요하지는 않습니다. (명시 적이거나 부족한 경우) 암시 적으로 선택 CXX=...합니다.

OS X 10.7 및 10.8에서 너무 많은 문제를 일으키는 경우는 다음과 같습니다 c++ -v -std=c++11 -x c++ - < /dev/null. 나는 grep'd덤프 된 디렉토리를 포함, 그들은 할 수 없습니다 포함한다 unique_ptr.

0

옵션 5 : 직접 별명.

#if __cplusplus >= 201103L
template<typename T> 
using MyPtr = std::unique_ptr<T>;
#else 
#define MyPtr std::auto_ptr
#endif 

장단점 :

  1. 최신 언어 버전 인 AKA C ++ 11 이상에서는 별칭 유형이 올바른 스마트 포인터에 매핑됩니다. 실제로 std :: auto_ptr과 관련된 API에 의존하는 모든 사용자 코드는 컴파일러에 의해 플래그가 지정되므로 실제로 수정 될 것입니다.

  2. 레거시 c ++ 03 모드에서 유형 별명은 매크로입니다. 이것은 거칠지 만 결과 구문 MyPtr<T>은 나머지 코드 전체에서 C ++ 11 사례와 동일합니다.

  3. MyPtr이를 설정 하려면 모든 auto_ptr 변수를 찾아서 변경해야합니다 .


1
이것이 무엇을 참조하는지는 확실하지 않습니다 (구문대로 전혀 질문이 아닙니다).
autophage

1
@ autophage 나는 그 대답을 믿습니다 ... 아마도 질문이 아닙니다.
Kain0_0
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.