커스텀 컨테이너를 구현할 때 반복기를 구현해야하는 지점에 도달했습니다. 물론 나는 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 년부터입니다. 조사를 해보니 첫 번째 버전이 널리 사용되지 않는 것 같지만 그 이유를 알 수 없습니다. 첫 번째 버전의 명백한 결함이 누락 된 것 같습니다.
따라서 질문은 다음과 같습니다.
첫 번째 버전에 문제가 있습니까?
그렇지 않다면 왜 버전 # 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] 삭제
몇 마디 만하겠습니다