[C++] 스터디 CPPALOM 9주차: 뇌를 자극하는 C++ STL Chap 7,9
파워 포인트 파일(.pptx)을 Markdown으로 변환하여 업로드하였음)
# <br>CPPALOM # <br>9주차 – 뇌를 자극하는 C++ STL Chap 7,9 한수빈 # <br>set 컨테이너 연관 컨테이너 중 단순한 컨테이너로, key라 불리는 원소(value)의 집합으로 이뤄진 컨테이너이다. 연관 컨테이너는 균형 이진 트리를 사용하므로 찾기 연산에서 로그 시간의 복잡도를 보인다. ![](img%5Cweek9_subin0.png) # <br>set 컨테이너에서의 삽입 set 컨테이너는 중복 삽입을 허용하지 않는다. 또한 원소는 자동 정렬되며 정렬 기준으로 less를 사용한다. ```C++ #include <iostream> #include <set> using namespace std; void main( ) { set<int> s; // 정수 원소를 저장하는 기본 정렬 기준이 less인 빈 컨테이너 생성 s.insert(50); //랜덤으로 원소(key)를 삽입한다. s.insert(30); s.insert(80); s.insert(40); s.insert(10); s.insert(70); s.insert(90); set<int>::iterator iter; // 기본 정렬 기준이 less인 set의 양방향 반복자 for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; // inorder 2진 트리 탐색 순서로 출력된다. cout << endl; s.insert(50); //중복된 원소(key)를 삽입한다. 실패!! s.insert(50); for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; // 결과는 같다. cout << endl; } ``` ```C++ 10 30 40 50 70 80 90 10 30 40 50 70 80 90 ``` insert()는 삽입 결과를 알려주는 pair 객체를 반환한다. first의 경우 삽입할 원소의 위치를 나타내는 반복자, second의 경우 성공 혹은 실패를 나타내는 불리언 값이다. ```C++ void main( ) { set<int> s; pair<set<int>::iterator, bool> pr; pr = s.insert(50); // 50 원소의 첫 번째 삽입 s.insert(40); s.insert(80); if( true == pr.second ) cout << *pr.first << " 삽입 성공!" << endl; else cout << *pr.first << "가 이미 있습니다. 삽입 실패!" << endl; set<int>::iterator iter; for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; cout << endl; pr = s.insert(50); // 50 원소의 두 번째 삽입. 실패!! if( true == pr.second ) cout << *pr.first << " 삽입 성공!" << endl; else cout << *pr.first << "가 이미 있습니다. 삽입 실패!" << endl; for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; cout << endl; } ``` ```C++ 50 삽입 성공! 40 50 80 50가 이미 있습니다. 삽입 실패! 40 50 80 ``` # <br>set 컨테이너 정렬 기준 변경 템플릿의 두번째 인자를 이용해 정렬 기준을 바꿀 수 있다. ```C++ #include <iostream> #include <set> using namespace std; void main( ) { set<int, greater<int> > s; // 정렬 기준으로 greater<int> 조건자를 사용. s.insert(50); s.insert(30); s.insert(80); s.insert(40); s.insert(10); s.insert(70); s.insert(90); // greater<int> 조건자를 사용하는 반복자 생성 set<int, greater<int> >::iterator iter; for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; cout << endl; } ``` ```C++ 90 80 70 50 40 30 10 ``` # <br>set::key_comp() set은 사용 중인 정렬 기준 조건자를 반환하는 key_comp()와 value_comp()를 제공한다. ```C++ #include <iostream> #include <set> using namespace std; void main( ) { set<int, less<int> > s_less; // set<int> s와 같습니다. set<int, greater<int> > s_greater; // 정렬 기준으로 greater<int> 조건자를 사용. s_less.insert(50); s_less.insert(80); s_less.insert(40); s_greater.insert(50); s_greater.insert(80); s_greater.insert(40); set<int, less<int> >::key_compare l_cmp=s_less.key_comp(); cout << l_cmp(10, 20) << endl; // 10 < 20 연산 set<int, greater<int> >::key_compare g_cmp=s_greater.key_comp(); cout << g_cmp(10, 20) << endl; // 10 > 20 연산 cout <<"key_compare type: " << typeid( s_less.key_comp() ).name() << endl; cout <<"key_compare type: " << typeid( s_greater.key_comp() ).name() << endl; cout <<"value_compare type: " << typeid( s_less.value_comp() ).name() << endl; cout <<"value_compare type: " << typeid( s_greater.value_comp() ).name() << endl; } ``` ```C++ 1 0 key_compare type: struct std::less<int> key_compare type: struct std::greater<int> value_compare type: struct std::less<int> value_compare type: struct std::greater<int> ``` # <br>set::lower_bound()comp() ```C++ void main( ) { set<int> s; s.insert(50); s.insert(30); s.insert(80); s.insert(40); s.insert(10); s.insert(70); s.insert(90); set<int>::iterator iter; for( iter = s.begin() ; iter != s.end() ; ++iter) cout << *iter << " "; cout << endl; set<int>::iterator iter_lower; set<int>::iterator iter_upper; iter_lower = s.lower_bound(30); iter_upper = s.upper_bound(30); cout << *iter_lower << endl; cout << *iter_upper << endl; iter_lower = s.lower_bound(55); iter_upper = s.upper_bound(55); if( iter_lower != iter_upper) cout << "55가 s에 있음!" << endl; else cout << "55가 s에 없음!" << endl; } ``` * key의 원소 구간을 반환하는 lower_bound()와 upper_bound()를 제공한다. * 중복 key가 없는 set에서 이는 큰 의미가 없지만, 중복 원소를 갖는 multiset이나 multimap에서는 유용하게 사용된다. ```C++ 10 30 40 50 70 80 90 30 40 55가 s에 없음! ``` # <br>set의 주요 특징 정리 * set은 대표적인 연관 컨테이너이자 노드 기반 컨테이너이다. * 연관 컨테이너는 특정 정렬 기준에 의해 원소가 자동 정렬되는 컨테이너이다. * 균형 이진 트리로 구현된다. * 연관 컨테이너는 모두 같은 인터페이스의 멤버 함수를 제공한다. # <br>multiset 컨테이너 중복 원소를 컨테이너에 저장할 수 있다는 것 외에는 set과 다른 것이 없다. multiset의 insert()는 key가 중복 저장될 수 있기 때문에 저장된 위치만을 가리키는 반복자를 반환한다. ```C++ #include <iostream> #include <set> using namespace std; void main( ) { multiset<int> ms; multiset<int>::iterator iter; ms.insert(50); ms.insert(30); ms.insert(80); ms.insert(80); // 80 중복 ms.insert(30); // 30 중복 ms.insert(70); iter = ms.insert(10); cout << "iter의 원소: " << *iter << endl; for( iter = ms.begin() ; iter != ms.end() ; ++iter) cout << *iter << " "; cout << endl; } ``` ![](img%5Cweek9_subin1.png) ```C++ iter의 원소: 10 10 30 30 50 70 80 80 ``` # <br>multiset의 찾기 관련 함수 ```C++ void main( ) { multiset<int> ms; ms.insert(50); ms.insert(30); ms.insert(80); ms.insert(80); // 80 중복 ms.insert(30); // 30 중복 ms.insert(70); ms.insert(10); multiset<int>::iterator iter; for( iter = ms.begin() ; iter != ms.end() ; ++iter) cout << *iter << " "; cout << endl; cout <<"30 원소의 개수: " << ms.count(30) << endl; // 30 원소의 개수 iter = ms.find(30); // 30 첫 번째 원소의 반복자 cout << "iter: " << *iter<< endl; multiset<int>::iterator lower_iter; multiset<int>::iterator upper_iter; lower_iter = ms.lower_bound(30); // 30 순차열의 시작 반복자 upper_iter = ms.upper_bound(30); // 30 순차열의 끝 표시 반복자 cout <<"lower_iter: " << *lower_iter <<", " <<"upper_iter: " << *upper_iter << endl; cout <<"구간 [lower_iter, upper_iter)의 순차열: " ; for( iter = lower_iter ; iter != upper_iter ; ++iter) cout << *iter << " "; cout << endl; } ``` * multiset은 count(), find(), lower_bound(), upper_bound(), equal_range() 멤버 함수를 제공한다. * 이 멤버 함수들은 중복 원소를 찾는 데 유용하게 사용된다. * 다음은 find(), count(), lower_bound(), upper_bound()의 예이다. ```C++ 10 30 30 50 70 8080 30 원소의 개수: 2 iter: 30 lower_iter: 30, upper_iter: 50 구간 [lower_iter, upper_iter)의 순차열: 30 30 ``` * multiset은 count(), find(), lower_bound(), upper_bound(), equal_range() 멤버 함수를 제공한다. * 이 멤버 함수들은 중복 원소를 찾는 데 유용하게 사용된다. * 다음은 equal_range()의 예이다. ```C++ void main( ) { multiset<int> ms; ms.insert(50); ms.insert(30); ms.insert(80); ms.insert(80); // 80 중복 ms.insert(30); // 30 중복 ms.insert(70); ms.insert(10); multiset<int>::iterator iter; for( iter = ms.begin() ; iter != ms.end() ; ++iter) cout << *iter << " "; cout << endl; //multiset의 반복자 쌍(pair) 객체 생성 pair<multiset<int>::iterator, multiset<int>::iterator> iter_pair; iter_pair = ms.equal_range(30); for( iter = iter_pair.first ; iter != iter_pair.second ; ++iter) cout << *iter << " "; //[iter_pair.first, iter_pair.second) 구간의 순차열 cout << endl; } ``` ```C++ 10 30 30 50 70 80 80 30 30 ``` # <br>map 컨테이너 * map 컨테이너는 key와 value의 쌍으로 저장한다. * map도 연관 컨테이너이므로 set과 같은 인터페이스 멤버 함수를 제공하며 템플릿 형식과 내장 멤버 형식만이 약간의 차이를 보인다. * 특히, map은 [] 연산자를 제공하여 key에 해당하는 원소의 value에 쉽게 접근하거나 변경할 수 있다. ![](img%5Cweek9_subin2.png) # <br>map::insert() map의 insert() 멤버 함수는 pair 객체를 인자로 받아 map의 원소인 key와 value 쌍을 저장한다. 반환되는 값은 삽입 결과이며, set의 경우와 동일하다. ```C++ void main( ) { //key, value 모두 정수형인 컨테이너 생성 //기본 정렬 기준 less map<int,int> m; m.insert( pair<int,int>(5,100) ); // 임시 pair 객체 생성 후 저장 m.insert( pair<int,int>(3,100) ); m.insert( pair<int,int>(8,30) ); m.insert( pair<int,int>(4,40) ); m.insert( pair<int,int>(1,70) ); m.insert( pair<int,int>(7,100) ); pair<int, int> pr(9,50); m.insert( pr ); // pr 객체 생성 후 저장 map<int,int>::iterator iter; for( iter = m.begin() ; iter != m.end() ; ++iter) cout <<"("<< (*iter).first <<',' << (*iter).second <<")" <<" "; cout << endl; // 반복자는 -> 연산자가 연산자 오버로딩되어 있으므로 //포인터처럼 멤버를 -> 연산자로 접근할 수 있습니다. for( iter = m.begin() ; iter != m.end() ; ++iter) cout <<"("<< iter->first <<',' << iter->second <<")" <<" "; cout << endl; } ``` ```C++ (1, 70) (3, 100) (4, 40) (5, 100) (7, 100) (8, 30) (9, 50) (1, 70) (3, 100) (4, 40) (5, 100) (7, 100) (8, 30) (9, 50) ``` # <br>map의 주요 특징 정리 * map은 대표적인 연관 컨테이너이자 노드 기반 컨테이너이다. * 연관 컨테이너는 특정 정렬 기준에 의해 원소가 자동 정렬되는 컨테이너이다. * 균형 이진 트리로 구현된다. * 연관 컨테이너는 모두 같은 인터페이스의 멤버 함수를 제공한다. * map은 key와 value의 쌍으로 이루어진다. * map은 [] 연산자를 이용해 원소를 추가하거나 key에 매핑된 value의 참조를 반환할 수 있다. # <br>multimap 컨테이너 ```C++ #include <iostream> #include <map> using namespace std; void main( ) { multimap<int,int> mm; mm.insert( pair<int,int>(5, 100) ); mm.insert( pair<int,int>(3, 100) ); mm.insert( pair<int,int>(8, 30) ); mm.insert( pair<int,int>(3, 40) ); mm.insert( pair<int,int>(1, 70) ); mm.insert( pair<int,int>(7, 100) ); mm.insert( pair<int,int>(8, 50) ); multimap<int,int>::iterator iter; for( iter = mm.begin() ; iter != mm.end() ; ++iter) cout <<"("<< iter->first <<',' << iter->second <<")" <<" "; cout << endl; cout << "key 3의 원소의 개수는 " << mm.count(3) << endl; iter = mm.find( 3 ); if( iter != mm.end() ) cout << "첫 번째 key 3에 매핑된 value: " << iter->second << endl; } ``` map 컨테이너에 중복 원소를 허용해야 한다면 multimap 컨테이너를 사용한다. 다음은 count()와 find()의 사용 예이다. ```C++ (1, 70) (3, 100) (3, 40) (5, 100) (7, 100) (8, 30) (8 50) key 3의 원소의 개수는 2 첫 번째 key 3에 매핑된 value: 100 ``` ```C++ void main( ) { multimap<int,int> mm; mm.insert( pair<int,int>(5, 100) ); mm.insert( pair<int,int>(3, 100) ); mm.insert( pair<int,int>(8, 30) ); mm.insert( pair<int,int>(3, 40) ); mm.insert( pair<int,int>(1, 70) ); mm.insert( pair<int,int>(7, 100) ); mm.insert( pair<int,int>(8, 50) ); multimap<int,int>::iterator lower_iter; multimap<int,int>::iterator upper_iter; lower_iter = mm.lower_bound(3); upper_iter = mm.upper_bound(3); cout <<"구간 [lower_iter, upper_iter)의 순차열: "; multimap<int,int>::iterator iter; for( iter = lower_iter ; iter != upper_iter ; ++iter) cout << "(" << iter->first <<',' << iter->second <<") "; cout << endl; pair<multimap<int,int>::iterator, multimap<int,int>::iterator> iter_pair; iter_pair = mm.equal_range(3); cout <<"구간 [iter_pair.first, iter_pair.second)의 순차열: "; for( iter = iter_pair.first ; iter != iter_pair.second ; ++iter) cout << "(" << iter->first <<',' << iter->second <<") "; cout << endl; } ``` map 컨테이너에 중복 원소를 허용해야 한다면 multimap 컨테이너를 사용한다. 다음은 lower_buond(), upper_bound(), equal_range()의 사용 예이다. ```C++ 구간 [lower_iter, upper_iter)의 순차열: (3,100) (3,40) 구간 [iter_pair.first, iter_pair.second)의 순차열: (3,100) (3,40) ``` # <br>STL 함수 객체 * STL의 함수 객체는 다음 두 가지로 분류할 수 있다: * 일반 함수 객체: 특정 기능을 수행하는 함수 객체 * 산술 연산 함수 객체: 산술 연산 기능을 수행(plus, minus, multiplies, divides, modulus, negate) * 비교 연산 함수 객체 조건자: 비교 조건자(equal_to, not_equal_to, less, greater, greater_equal, less_equal) * 논리 연산 함수 객체 조건자: 논리 조건자(logical_and, logical_or, logical_not) * 함수 어댑터(function adaptor): 함수류(함수 객체, 함수, 함수 푕ㄴ터)를 인자로 받아 다른 함수 객체로 변환 * 바인더(binder): 이항 함수 객체를 단항 함수 객체로 반환(bind1st, bind2nd) * 부정자(negator): 함수 객체 조건자를 반대로 변환(not1, not2) * 함수 포인터 어댑터: 함수 포인터를 STL이 요구하는 함수 객체로 변환(ptr_fun) * 멤버 함수 포인터 어댑터: 멤버 함수 포인터를 STL이 요구하는 함수 객체로 변환(mem_fun, mem_fun_ref) # <br>조건자 * 조건자는 bool 형식을 반환하는 함수류이다. * STL에서 제공하는 조건자는 모두 함수 객체 조건자이다. * 조건자는 해당 객체의 상태값을 변경할 수 없어야 한다. * 따라서, 함수 객체 조건자의 operator() 연산자 오버로딩 함수는 모두 const 함수이다. ```C++ struct LessFunctor // 1. 함수 객체 조건자 { bool operator()(int left, int right) const { return left < right; } }; bool LessFun(int left, int right) // 2. 함수 조건자 { return left < right; } void main( ) { bool (*LessPtr)(int, int) = LessFun; // 3. 함수 포인터 조건자 LessFunctor lessFunctor; //모두 bool 형식을 반환 //1. 함수 객체로 10과 20을 비교 cout << lessFunctor(10, 20) << endl; //2. 함수로 10과 20을 비교 cout << LessFun(10, 20) << endl; //3. 함수 포인터로 10과 20을 비교 cout << LessPtr(10, 20) << endl; } ``` # <br>어댑터 단항 함수 객체는 argument_type, result_type이 정의되어 있어야 한다. 이항 함수 객체는 first_argument_type, second_argument_typoe, result_type이 정의되어 있어야 한다. 어댑터는 함수 객체를 다른 함수 객체로 변환할 때 위 정의 형식을 이용해 변환을 수행한다. 다음은 이항 함수 객체인 plus<int>의 한 인자를 100으로 고정하고 두번째 인자만을 입력 받게 변경하는 예이다. ```C++ template<typename T> struct Plus { T operator( )(const T& left, const T& right) const { return left + right; } }; void main( ) { vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); vector<int> v3(3); //size: 3인 vector 생성 //STL 조건자 plus<int> 사용 transform(v1.begin(), v1.end(), v3.begin(), binder1st<plus<int>> (plus<int>(), 100)); cout <<"v1 : "; for(vector<int>::size_type i = 0 ; i < v1.size() ; i++) cout << v1[i] << " "; cout << endl; cout <<"v3 : "; for(vector<int>::size_type i = 0 ; i < v3.size() ; i++) cout << v3[i] << " "; cout << endl; } ``` ```C++ v1 : 10 20 30 v3 : 110 120 130 ``` 사용자 함수 객체도 어댑터 적용이 가능하려면 필요한 변수들을 정의해주어야 한다. 이렇게 직접 함수자에 해당하는 변수들을 정의하여 사용할 수 있지만, unary_function과 binary_function을 상속받아 구현하는 것이 더 일반적이고 쉽다. ```C++ #include <iostream> #include <functional> #include <algorithm> #include <vector> using namespace std; template<typename T> struct Plus { typedef T first_argument_type; typedef T second_argument_type; typedef T result_type; T operator( )(const T& left, const T& right) const { return left + right; } }; ``` ```C++ template<typename T> struct Plus: public binary_function<T,T,T> { T operator( )(const T& left, const T& right) const { return left + right; } }; ``` # <br>산술 연산 함수 객체 plus<T>: 이항 연산 함수자로 + 연산 minus<T>: 이항 연산 함수자로 – 연산 multiplies<T>: 이항 연산 함수자로 * 연산 divides<T>: 이항 연산 함수자로 / 연산 modulus<T>: 이항 연산 함수자로 % 연산 negate<T>: 단항 연산 함수자로 - 연산 ```C++ #include <iostream> #include <functional> using namespace std; template<typename T> struct Plus: public binary_function<T,T,T> //어댑터 적용이 가능하도록. { T operator( )(const T& left, const T& right) const { return left + right; } }; void main( ) { Plus<int> oPlus; cout << oPlus(10, 20) << endl; cout << oPlus.operator()(10,20) << endl; cout << Plus<int>()(10, 20) << endl; cout << Plus<int>().operator()(10, 20) << endl; } ``` # <br>비교 연산 조건자 equal_to<T>: 이항 조건자로 == 연산 not_equal_to<T>: 이항 조건자로 != 연산 less<T>: 이항 조건자로 < 연산 less_equal<T> 이항 조건자로 <= 연산 greater<T>: 이항 조건자로 > 연산 greater_equal<T>: 이항 조건자로 >= 연산 ```C++ #include <iostream> #include <functional> using namespace std; template<typename T> struct Less: public binary_function<T,T,bool> //어댑터 적용이 가능하도록. { bool operator( )(const T& left, const T& right) const { return left < right; } }; void main( ) { Less<int> oLess; cout << oLess(10, 20) << endl; cout << oLess.operator()(10,20) << endl; cout << Less<int>()(10, 20) << endl; cout << Less<int>().operator()(10, 20) << endl; } ``` # <br>논리 연산 조건자 logical_and<T>: 이항 조건자로 && 연산 logical_or<T>: 이항 조건자로 || 연산 logical_not<T>: 이항 조건자로 ! 연산 ```C++ template<typename T> struct Logical_and: public binary_function<T,T,bool> //어댑터 적용이 가능하도록. { bool operator( )(const T& left, const T& right) const { return left && right; } }; void main( ) { int n = 30; logical_and<bool> oAnd; //1. oAnd 객체로 10 < n < 50 인가? true. 암묵적 호출 cout << oAnd( greater<int>()(n, 10), less<int>()(n, 50) ) << endl; //2. oAnd 객체로 10 < n < 50 인가? true. 명시적 호출 cout << oAnd.operator()( greater<int>()(n, 10), less<int>()(n, 50) ) << endl; //3. 임시 객체로 10 < n < 50 인가? true. 암묵적 호출(일반적인 사용) cout << logical_and<bool>()( greater<int>()(n, 10), less<int>()(n, 50) ) << endl; //4. 임시 객체로 10 < n < 50 인가? true. 명시적 호출 cout << logical_and<bool>().operator()( greater<int>()(n, 10), less<int>()(n, 50) ) << endl; } ``` # <br>바인더 bind1st: 이항 함수자의 첫 번째 인자를 고정하여 단항 함수자로 변환 bind2nd: 이항 함수자의 두 번째 인자를 고정하여 단항 함수자로 변환 ```C++ #include <iostream> #include <functional> using namespace std; void main() { //less의 첫 인자를 10으로 고정한 단항 조건자 binder 생성. binder1st< less<int> > binder = bind1st(less<int>(), 10 ); // binder는 첫 번째 인자를 10으로 고정한 less. cout << binder(5) <<':'<< less<int>()(10, 5) << endl; // 두 문장이 동일합니다. cout << binder(10) <<':'<< less<int>()(10, 10) << endl;// 두 문장이 동일합니다. cout << binder(20) <<':'<< less<int>()(10, 20) << endl;// 두 문장이 동일합니다. cout << "=====위와 같음=====" << endl; // 임시 객체 사용 cout << bind1st(less<int>(), 10 )(5) <<':'<< less<int>()(10, 5) << endl; cout << bind1st(less<int>(), 10 )(10) <<':'<< less<int>()(10, 10) << endl; cout << bind1st(less<int>(), 10 )(20) <<':'<< less<int>()(10, 20) << endl; } ``` ```C++ 0:0 0:0 1:1 =====위와 같음===== 0:0 0:0 1:1 ``` # <br>부정자 not1: 단항 조건자를 반대의 조건자로 변환 not2: 이항 조건자를 반대의 조건자로 변환 ```C++ #include <iostream> #include <functional> using namespace std; void main( ) { less<int> oLess; binary_negate< less<int> > negate= not2(less<int>()); cout << negate(5, 10) <<':'<< not2(oLess)(5, 10) <<':'<< not2( less<int>() )(5, 10) << endl; //모두 같다. cout << negate(10, 10) <<':'<< not2(oLess)(10, 10) <<':'<< not2( less<int>() )(10, 10) << endl; //모두 같다. cout << negate(20, 10) <<':'<< not2(oLess)(20, 10) <<':'<< not2( less<int>() )(20, 10) << endl; //모두 같다. } ``` ```C++ 0:0:0 1:1:1 1:1:1 ``` # <br>함수 포인터 어댑터 * 함수 포인터 어댑터는 일반 함수를 어댑터 적용이 가능한 함수 객체로 변환한다. * STL은 ptr_fun()이라는 함수 포인터 어댑터를 제공한다. ```C++ bool Pred(int n) { return 30 <= n && n <= 40; } void main( ) { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); cout <<"v : "; for(vector<int>::size_type i = 0 ; i < v.size() ; i++) cout << v[i] << " "; cout << endl; cout<<"30이상 40이하의 원소 개수: " << count_if(v.begin(), v.end(), Pred) << endl; //다음은 에러입니다. not1은 어댑터로 함수 객체에 argument_type, result_type가 정의되어 있어야 함! cout<<"30이상 40이하가 아닌 원소 개수: " << count_if(v.begin(), v.end(), not1(Pred) ) << endl; } ``` * 함수 포인터 어댑터는 일반 함수를 어댑터 적용이 가능한 함수 객체로 변환한다. * STL은 ptr_fun()이라는 함수 포인터 어댑터를 제공한다. * 다음은 에러가 나는 코드이다. ```C++ bool Pred(int n) { return 30 <= n && n <= 40; } void main( ) { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); cout <<"v : "; for(vector<int>::size_type i = 0 ; i < v.size() ; i++) cout << v[i] << " "; cout << endl; cout<<"30이상 40이하의 원소 개수: " << count_if(v.begin(), v.end(), Pred) << endl; //다음은 에러입니다. not1은 어댑터로 함수 객체에 argument_type, result_type가 정의되어 있어야 함! cout<<"30이상 40이하가 아닌 원소 개수: " << count_if(v.begin(), v.end(), not1(Pred) ) << endl; } ``` * 함수 포인터 어댑터는 일반 함수를 어댑터 적용이 가능한 함수 객체로 변환한다. * 따라서 이런 함수 자체를, 사양에 맞는 적절한 함수 객체로 변환시킬 수 있다. ```C++ bool Pred(int n) { return 30 <= n && n <= 40; } void main( ) { vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); cout <<"v : "; for(vector<int>::size_type i = 0 ; i < v.size() ; i++) cout << v[i] << " "; cout << endl; cout<<"30이상 40이하의 원소 개수: " << count_if(v.begin(), v.end(), Pred) << endl; //가능~! cout<<"30이상 40이하가 아닌 원소 개수: " << count_if(v.begin(), v.end(), not1( ptr_fun(Pred) ) ) << endl; } ``` ```C++ v : 10 20 30 40 50 30이상 40이하의 원소 개수: 2 30이상 40이하가 아닌 원소 개수: 3 ``` # <br>멤버 함수 포인터 어댑터 * 멤버 함수 포인터 어댑터는 멤버 함수를 함수 객체로 변환하여 알고리즘이 객체 원소의 멤버 함수를 호출할 수 있게 한다. * 따라서 이런 함수 자체를, 사양에 맞는 적절한 함수 객체로 변환시킬 수 있다. ```C++ class Point { int x; int y; public: explicit Point(int _x =0 , int _y =0 ):x(_x),y(_y) { } void Print( ) const { cout << x <<',' << y << endl; } int GetX() const { return x; } int GetY() const { return y; } }; void main() { vector<Point> v; v.push_back( Point(1,1) ); v.push_back( Point(2,2) ); v.push_back( Point(3,3) ); v.push_back( Point(4,4) ); v.push_back( Point(5,5) ); // 호출 불가능 //for_each(v.begin(), v.end(), &Point::Print ); // 호출 가능 for_each(v.begin(), v.end(), mem_fun_ref(&Point::Print) ); } ``` ```C++ 1,1 2,2 3,3 4,4 5,5 ```
댓글
댓글 쓰기