C ++ 17에서 반복기와 const_iterator를 구현하는 올바른 방법은 무엇입니까?

Churill

커스텀 컨테이너를 구현할 때 반복기를 구현해야하는 지점에 도달했습니다. 물론 나는 const와 non-const iterator에 대해 코드를 두 번 작성하고 싶지 않았습니다. 다음 과 같은 가능한 구현을 자세히 설명하는 이 질문을 찾았습니다 .

template<class T>
class ContainerIterator {
    using pointer = T*;
    using reference = T&;
    ...
};

template<class T>
class Container {
    using iterator_type = ContainerIterator<T>;
    using const_iterator_type = ContainerIterator<const T>;
}

그러나 템플릿 매개 변수를 사용하는 다음 질문 도 발견했습니다 .

template<class T, bool IsConst>
class ContainerIterator {
    using pointer = std::conditional_t<IsConst, const T*, T*>;
    using reference = std::conditional_t<IsConst, const T&, T&>;
    ...
};

template<class T>
class Container {
    using iterator_type = ContainerIterator<T, false>;
    using const_iterator_type = ContainerIterator<T, true>;
}

첫 번째 해결책은 더 쉬운 것 같지만 답은 2010 년부터입니다. 조사를 해보니 첫 번째 버전이 널리 사용되지 않는 것 같지만 그 이유를 알 수 없습니다. 첫 번째 버전의 명백한 결함이 누락 된 것 같습니다.


따라서 질문은 다음과 같습니다.

  1. 첫 번째 버전에 문제가 있습니까?

  2. 그렇지 않다면 왜 버전 # 2가 C ++ 17에서 선호되는 방법 인 것 같습니까? 아니면 왜 다른 것보다 하나를 선호해야합니까?


또한 예, const_cast 전체 코드 를 사용 하거나 단순히 복제 하는 솔루션이 될 것 입니다. 그러나 나는 그 두 가지를 좋아하지 않는다.

니콜 볼 라스

두 번째 구현의 요점은 특정 요구 사항을 쉽게 구현하기 위해 복사하지 않은 것입니다. 즉,는 iterator암시 적으로 const_iterator.

여기서 어려움은 사소한 복사 가능성을 유지하는 데 있습니다. 이렇게하려면 :

template<class T>
class ContainerIterator {
    using pointer = T*;
    using reference = T&;
    ...
    ContainerIterator(const ContainerIterator &) = default; //Should be trivially copyable.
    ContainerIterator(const ContainerIterator<const T> &) {...}
};

작동하지 않습니다. const const Typename아래로 해결합니다 const Typename. 따라서를 ContainerIterator사용하여 인스턴스화 const T하면 이제 동일한 서명을 가진 두 개의 생성자가 있으며 그중 하나는 기본값입니다. 이것은 컴파일러가 복사 생성자의 기본값을 무시하므로 사소하지 않은 복사 생성자 구현을 사용한다는 것을 의미합니다.

그 나쁜.

일부 메타 프로그래밍 도구를 사용하여의 const-ness를 감지하여이를 피하는 방법이 T있지만이를 수정하는 가장 쉬운 방법은 const-ness를 템플릿 매개 변수로 지정하는 것입니다.

template<class T, bool IsConst>
class ContainerIterator {
    using pointer = std::conditional_t<IsConst, const T*, T*>;
    using reference = std::conditional_t<IsConst, const T&, T&>;
    ...

    ContainerIterator(const ContainerIterator &) = default; //Should be trivially copyable.
    template<bool was_const = IsConst, class = std::enable_if_t<IsConst || !was_const>>>
    ContainerIterator(const ContainerIterator<T, was_const> &) {...}
};

템플릿은 복사 생성자로 간주되지 않으므로 사소한 복사 가능성을 방해하지 않습니다. 이것은 또한 SFINAE를 사용하여 const반복자 가 아닌 경우 변환 생성자를 제거 합니다.

이 패턴에 대한 자세한 정보도 찾을 수 있습니다 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

C ++ 11에서 벡터를 반복하는 가장 현대적인 방법, 가장 "올바른"방법은 무엇입니까?

분류에서Dev

기존 포인터 대신 C ++ stl 반복기를 사용하는 올바른 방법은 무엇입니까?

분류에서Dev

C #에서 올바른 BackGroundImage를 설정하는 방법은 무엇입니까?

분류에서Dev

조명기에서 구조화 된 데이터를 반환하는 올바른 방법은 무엇입니까?

분류에서Dev

Extern "C"의 벡터 <std :: string>에 List <String ^>을 (를) 반환하는 올바른 방법은 무엇입니까?

분류에서Dev

c에서 strcpy를 올바르게 구현하는 방법은 무엇입니까?

분류에서Dev

C에서 함수 포인터를 포함하는 구조체를 만들고 초기화하는 올바른 방법은 무엇입니까?

분류에서Dev

GRPC C ++ 서버 구현에서 '찾을 수 없음'응답을 반환하는 올바른 방법은 무엇입니까?

분류에서Dev

PGdata 폴더에서 Postgres 데이터베이스를 복구하는 올바른 방법은 무엇입니까?

분류에서Dev

C ++에서 반복기 만 사용하여 3D 벡터를 올바르게 반복하는 방법은 무엇입니까?

분류에서Dev

GitHub에서 복제 된 저장소의 올바른 크기를 확인하는 방법은 무엇입니까?

분류에서Dev

일반 콜백에서 비동기 코드를 호출하는 올바른 방법은 무엇입니까?

분류에서Dev

C ++ 17 파일 시스템을 CMake와 연결하는 올바른 방법은 무엇입니까?

분류에서Dev

C ++에서 구조체 세트를 갖는 올바른 방법은 무엇입니까?

분류에서Dev

IFormFile에 대한 Fluent 유효성 검사를 구현하는 올바른 방법은 무엇입니까?

분류에서Dev

바이너리 버퍼에서 변수를 초기화하는 올바른 방법은 무엇입니까?

분류에서Dev

ASP.NET C #의 EventHandler에서 페이지를 수정하는 올바른 방법은 무엇입니까?

분류에서Dev

C ++에서 QML 객체를 업데이트하는 올바른 방법은 무엇입니까?

분류에서Dev

C ++에서 생성자를 호출하는 올바른 방법은 무엇입니까?

분류에서Dev

Objective-C에서 전역 변수를 선언하는 올바른 방법은 무엇입니까?

분류에서Dev

Android에서 회전 된보기를 올바른 방향으로 이동하는 방법은 무엇입니까?

분류에서Dev

문제를 방지하기 위해 C에서 문자열을 읽는 올바른 방법은 무엇입니까?

분류에서Dev

C ++ 11 스레드를 사용하여 결과를 반환하는 올바른 방법은 무엇입니까?

분류에서Dev

unorder_map :: const_iterator와 함께 typedef를 사용하는 방법은 무엇입니까?

분류에서Dev

Firebase에서 데이터를 복제하는 올바른 방법은 무엇입니까?

분류에서Dev

MFC로 큐를 구현하는 올바른 방법은 무엇입니까?

분류에서Dev

React + Redux에서 감속기에 인수를 전달하는 올바른 방법은 무엇입니까?

분류에서Dev

typescript에서`payload is T`를 반환 할 때 올바른 유형을 추론하는 방법은 무엇입니까?

분류에서Dev

Rails API에서 올바른 필드를 반환하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    C ++ 11에서 벡터를 반복하는 가장 현대적인 방법, 가장 "올바른"방법은 무엇입니까?

  2. 2

    기존 포인터 대신 C ++ stl 반복기를 사용하는 올바른 방법은 무엇입니까?

  3. 3

    C #에서 올바른 BackGroundImage를 설정하는 방법은 무엇입니까?

  4. 4

    조명기에서 구조화 된 데이터를 반환하는 올바른 방법은 무엇입니까?

  5. 5

    Extern "C"의 벡터 <std :: string>에 List <String ^>을 (를) 반환하는 올바른 방법은 무엇입니까?

  6. 6

    c에서 strcpy를 올바르게 구현하는 방법은 무엇입니까?

  7. 7

    C에서 함수 포인터를 포함하는 구조체를 만들고 초기화하는 올바른 방법은 무엇입니까?

  8. 8

    GRPC C ++ 서버 구현에서 '찾을 수 없음'응답을 반환하는 올바른 방법은 무엇입니까?

  9. 9

    PGdata 폴더에서 Postgres 데이터베이스를 복구하는 올바른 방법은 무엇입니까?

  10. 10

    C ++에서 반복기 만 사용하여 3D 벡터를 올바르게 반복하는 방법은 무엇입니까?

  11. 11

    GitHub에서 복제 된 저장소의 올바른 크기를 확인하는 방법은 무엇입니까?

  12. 12

    일반 콜백에서 비동기 코드를 호출하는 올바른 방법은 무엇입니까?

  13. 13

    C ++ 17 파일 시스템을 CMake와 연결하는 올바른 방법은 무엇입니까?

  14. 14

    C ++에서 구조체 세트를 갖는 올바른 방법은 무엇입니까?

  15. 15

    IFormFile에 대한 Fluent 유효성 검사를 구현하는 올바른 방법은 무엇입니까?

  16. 16

    바이너리 버퍼에서 변수를 초기화하는 올바른 방법은 무엇입니까?

  17. 17

    ASP.NET C #의 EventHandler에서 페이지를 수정하는 올바른 방법은 무엇입니까?

  18. 18

    C ++에서 QML 객체를 업데이트하는 올바른 방법은 무엇입니까?

  19. 19

    C ++에서 생성자를 호출하는 올바른 방법은 무엇입니까?

  20. 20

    Objective-C에서 전역 변수를 선언하는 올바른 방법은 무엇입니까?

  21. 21

    Android에서 회전 된보기를 올바른 방향으로 이동하는 방법은 무엇입니까?

  22. 22

    문제를 방지하기 위해 C에서 문자열을 읽는 올바른 방법은 무엇입니까?

  23. 23

    C ++ 11 스레드를 사용하여 결과를 반환하는 올바른 방법은 무엇입니까?

  24. 24

    unorder_map :: const_iterator와 함께 typedef를 사용하는 방법은 무엇입니까?

  25. 25

    Firebase에서 데이터를 복제하는 올바른 방법은 무엇입니까?

  26. 26

    MFC로 큐를 구현하는 올바른 방법은 무엇입니까?

  27. 27

    React + Redux에서 감속기에 인수를 전달하는 올바른 방법은 무엇입니까?

  28. 28

    typescript에서`payload is T`를 반환 할 때 올바른 유형을 추론하는 방법은 무엇입니까?

  29. 29

    Rails API에서 올바른 필드를 반환하는 방법은 무엇입니까?

뜨겁다태그

보관