C++사용자 정의 형식의 교체 기 작업 실현
우 리 는 STL 이 많은 알고리즘(\#include
STL 의 교체 기
교체 기 모델 은 전형 적 인 디자인 모델 이 고 STL 의 교체 기 는 템 플 릿 의 일부 특성 과 기능 을 사용 하 는 것 을 실현 하 였 으 며 여기 서 조금 소개 하 겠 습 니 다.
다음은 STL 에서 구조 체 iterator 의 정의 입 니 다.이 정 의 는 뒤의 알고리즘 다 형 과 추출 시(구체 적 으로 책 에서 소개)에 사 용 됩 니 다.
그 중의Category 와Ty 는 기본 값 이 없어 서 스스로 인 자 를 줘 야 합 니 다.
_Ty 는 원소 의 유형 입 니 다.
template<class _Category,
class _Ty,
class _Diff = ptrdiff_t,
class _Pointer = _Ty *,
class _Reference = _Ty&>
struct iterator
{ // base type for iterator classes
typedef _Category iterator_category;
typedef _Ty value_type;
typedef _Diff difference_type;
typedef _Diff distance_type; // retained
typedef _Pointer pointer;
typedef _Reference reference;
};
그리고Category 는 교체 기의 유형 으로 주로 다음 과 같은 몇 가지 가 있다.
// ITERATOR STUFF (from <iterator>)
// ITERATOR TAGS (from <iterator>)
struct input_iterator_tag //
{ // identifying tag for input iterators
};
struct _Mutable_iterator_tag //
{ // identifying tag for mutable iterators
};
struct output_iterator_tag //
: _Mutable_iterator_tag
{ // identifying tag for output iterators
};
struct forward_iterator_tag //
: input_iterator_tag, _Mutable_iterator_tag
{ // identifying tag for forward iterators
};
struct bidirectional_iterator_tag //
: forward_iterator_tag
{ // identifying tag for bidirectional iterators
};
struct random_access_iterator_tag //
: bidirectional_iterator_tag
{ // identifying tag for random-access iterators
};
//...
사용자 정의 교체 기나 는 교체 기 에 다음 과 같은 조작 이 있 기 를 바란다.*,+.또한 교체 기 를 통 해 count 를 호출 하려 고 합 니 다.if 함수.그럼 countif 어떤 조작 부 호 를 사용 하 시 겠 습 니까?
// TEMPLATE FUNCTION count_if
template<class _InIt,
class _Pr> inline
typename iterator_traits<_InIt>::difference_type
_Count_if(_InIt _First, _InIt _Last, _Pr _Pred)
{ // count elements satisfying _Pred
typename iterator_traits<_InIt>::difference_type _Count = 0;
for (; _First != _Last; ++_First)
if (_Pred(*_First))
++_Count;
return (_Count);
}
++를 사용 하 는 것 을 볼 수 있 습 니 다.그래서 우리 의 교체 기 는 이것 을 모두 실현 해 야 한다.코드 는 간단 합 니 다:
#include<iterator>
template<class T>
class MyIterator : public iterator<input_iterator_tag, T>{
public:
MyIterator(T* p){
_ptr = p;
}
//
MyIterator& operator = (const MyIterator &iter)
{
_ptr = iter._ptr;
}
//
bool operator != (const MyIterator &iter)
{
return _ptr!= iter._ptr;
}
//
bool operator == (const MyIterator &iter)
{
return _ptr == iter._ptr;
}
//
MyIterator& operator ++ ()
{
_ptr++;
return *this;
}
//
MyIterator operator ++ (int)
{
MyIterator tmp= *this;
_ptr++;
return tmp;
}
//
T& operator * ()
{
return *_ptr;
}
private:
T* _ptr;// ,
};
사용자 정의 용기다음은 간단 한 수조 용 기 를 제시 하여 수조 의 기본 조작 을 실현 하 였 다.방금 정 의 된 교체 기 를 내장 하 였 습 니 다.
template<class T>
class myVector{
public:
typedef MyIterator<T> iterator;// ,
myVector(){
_selfElems = new T[32];
_count = 32;
init();
}
myVector(int n){
_selfElems = new T[n];
_count = n;
init();
}
void init(){
memset(_selfElems, 0, sizeof(T)* _count);
}
//
T& operator[](int i){
return _selfElems[i];
}
iterator begin(){
return iterator(_selfElems);
}
iterator end(){
return iterator(_selfElems + _count);
}
int size() const {
return _count;
}
private:
T* _selfElems;
int _count;
};
\#\#테스트vector 와 자체 용기 my Vector 를 정의 하고 교체 기 를 통 해 접근 하 며 교체 기 를 통 해 conunt 를 사용 합 니 다.if 함수
bool eq_10(int k){
return k == 10;
}
int main(){
//
myVector<int> mv(10);
mv[3] = 10; mv[9] = 10;
myVector<int>::iterator it = mv.begin();
cout <<"mv:"<<endl;
while (it != mv.end()){
cout << *(it++) << " ";
}
cout << endl;
cout << count_if(mv.begin(), mv.end(), eq_10) << endl;
//STL
vector<int> v(10,0);
v[3] = 10; v[9] = 10;
vector<int>::iterator it1 = v.begin();
cout << "v:" << endl;
while (it1 != v.end()){
cout << *(it1++) << " ";
}
cout << endl;
cout << count_if(mv.begin(), mv.end(), eq_10) << endl;
getchar();
return 0;
총화 와 사고그래서 쉽게 말 하면 자신의 용기 의 교체 기 를 정의 하고 교체 기 를 통 해 STL 의 알고리즘 함 수 를 호출 하려 면.먼저 iteroter 를 계승 한 다음 에 필요 한 조작 부 호 를 실현 하면 됩 니 다.그러나 구체 적 인 알고리즘 함 수 는 교체 기 유형 에 대해 요구 가 있 기 때문에 이것 은 스스로 파악 해 야 한다.
이 간단 한 예제 에 서 는 my Vector 의 지침(mv.ptr)도 count 를 호출 할 수 있 습 니 다.if 의 경우 STL 이 템 플 릿 편 특 화 기술 을 통 해 교체 기 도 네 이 티 브 지침 을 지원 하기 때 문 입 니 다.그러나 방문 요 소 를 모두 교체 기 에 넣 었 으 니 모든 용기 에 대해 통 일 된 방식 으로 접근 할 수 있 습 니 다.모든 용기 의 디 테 일 을 드 러 내지 않 아 도 됩 니 다(my Vector:ptr):
//T
template<class T>
void display(T it, T end){
T it1 = it;
while (it1 != end){
cout << *(it1++) << " ";
}
cout << endl;
cout << count_if(it,end, eq_10) << endl;
}
int main(){
//
myVector<int> mv(10);
mv[3] = 10; mv[9] = 10;
//STL
vector<int> v(10, 0);
v[3] = 10; v[9] = 10;
//vector myVector ,
display(mv.begin(), mv.end());
display(v.begin(), v.end());
getchar();
return 0;
}
교체 기 는 용기 에 더 많은 기능 과 통용 성 을 부여 했다.추가 지식:C++사용자 정의 교체 기(구현+두 칸 증가)
//효 과 는 매번 교체 기 에 두 칸 씩 이동 합 니 다.
#pragma once
//MyIterator.h
#include <iterator>
#include <exception>
template<typename Container>
class MyIterator :public std::iterator<std::random_access_iterator_tag, typename Container::value_type>
{
protected:
Container& container;
typename Container::iterator pos;
public:
explicit MyIterator(Container& c) :container(c), pos(c.begin()){}
MyIterator(const MyIterator& rhs) :container(rhs.container),pos(rhs.pos) {}
MyIterator& operator =(const MyIterator& rhs)
{
throw_ex(rhs.container);
pos = rhs.pos;
return *this;
}
//-- ...
MyIterator& operator ++()
{
auto tmp = container.end() - 1;
if (pos == tmp)
++pos;
else
pos += 2;
return *this;
}
bool operator ==(const MyIterator& rhs)const
{
try
{
if (&rhs.container == &container)
return pos == rhs.pos;
else
{
throw exception(" ");
}
}
catch (exception &e)
{
cout << e.what();
exit(EXIT_FAILURE);
}
}
bool operator !=(const MyIterator& rhs)const
{
return !(*this == rhs);
}
typename Container::value_type & operator *()
{
return *pos;
}
void begin()
{
pos = container.begin();
}
void end()
{
pos = container.end();
}
private:
void throw_ex(const Container& c)
{
try
{
if (&c == &container)
return;
else
throw exception("Copy ");
}
catch (exception &e)
{
cout << e.what();
exit(EXIT_FAILURE);
}
}
};
// vector<T> vec vec.begin() begin(vec)
// start(vec) over(vec)
template<typename Container>
MyIterator<Container> start(Container& c)
{
MyIterator<Container> mi(c);
mi.begin();
return mi;
}
template<typename Container>
MyIterator<Container> over(Container & c)
{
MyIterator<Container> mi(c);
mi.end();
return mi;
}
//main.cpp
#include <iostream>
#include <vector>
#include "MyIterator.h"
#include <list>
using namespace std;
// iterator<std::random_access_iterator_tag,Container::value_type>
template<typename Iterator>
void printIterator(const Iterator &It)
{
cout << typeid(typename iterator_traits<Iterator>::iterator_category).name() << endl;
}
int main()
{
vector<int> coll{ 1,2,3,4,5,6,7,8,9,10 };
MyIterator<decltype(coll)> myit(coll);
printIterator(myit);
for (; myit != over(coll); ++myit)
{
cout << *myit << ends;
}
system("pause");
return 0;
}
효과:
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.잘못 이 있 거나 완전히 고려 되 지 않 은 곳 이 있 으 면 댓 글 토론 을 환영 합 니 다.아 낌 없 는 가르침 을 바 랍 니 다.