{{ label!='' ? 'Label : ' : (q!='' ? '검색 : ' : '전체 게시글') }} {{ label }} {{ q }} {{ ('('+(pubs|date:'yyyy-MM')+')') }}

[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
```

댓글

이 블로그의 인기 게시물

[코딩의탑] 4층: 툰 쉐이딩

[코딩의탑] 3층: 바다 렌더링

[코딩의탑] 5층: 포탈(Portal), 더 나아가기