C++11에서 STL bind Boost::bind를 같이 사용할 때 아래와 같이 사용하면 이름 충돌이 발생할 수 있습니다.


#include <functional>

using namespace std::placeholders;

#include <boost/bind.hpp>

 

int f(int, int);

auto g = std::bind(f, _1, 42);  // _1 때문에 에러 발생

 

해결 방법은 이름 공간을 정확하게 지정하면 됩니다.

auto g = std::bind(f, std::placeholders::_1, 42);

 

namespace ph = std::placeholders;

auto g = std::bind(f, ph::_1, 42);

 


 

출처 : http://d.hatena.ne.jp/yohhoy/20121129/p1

저작자 표시
신고
by 흥배 2013.03.29 08:00

표준 C++ 라이브러리가 제공하는 다양한 함수에는 1(혹은 2)의 인수를 주는 함수 오브젝트를 인도하는 것이 다수 있습니다.

 

정수는 몇 개?

#include <iostream>
#include <algorithm>

using namespace std;

 

// n정수라면 true를 돌려준다

bool is_positive( int n)

{

return n > 0;

}

 

int main()

{

const int N = 8;

int data[N] = { -3, -2, -1, 0, 1, 2, 3, 4 };

   /* count_if(first, last, pred):

* first이상 last미만의 범위에 있 x에 대해

* pred(*x) true (!=0) 되는 것의 개수를 돌려준다 */

cout << count_if(data, data+N, &is_positive) << " positives\n" ;

}

 

< 실행 결과 >

4 positives

 

 

표준 C++ 라이브러리의 함수 오브젝트 less를 사용 하여 상기의 is_positive로 옮겨지지 않는지 생각해 봅시다.

함수 오브젝트 less의 멤버 함수 operator()는 인수를 2개 취하여 1 인수가 2 인수 보다 작으면 true를 돌려줍니다.

 

 

함수 오브젝트 less

std::less< int > int_less;

bool result = int_less(1,2); // true

result = int_less(2,1); // false

result = int_less(2,2); // false

 

 

less를 방금 전의 알고리즘 :count_if의 제3인수에 사용하기 위해 binder1stless::operator() 1 인수를 0으로 속박(고정) 합니다.

 

bind1st/bind2nd에 의한 속박

#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

 

int main()

{

const int N = 8;

int data[N] = { -3, -2, -1, 0, 1, 2, 3, 4 };

// 1인수를 0으로 속박 하는 것으로,

// 인수가 정수라면 true를 돌려주는 함수 오브젝트가 된다.

cout << count_if(data, data+N, bind1st(less< int >(),0)) << " positives\n" ;

// 2인수를 0으로 속박 하면 정수라면 true를 돌려준다.

cout << count_if(data, data+N, bind2nd(less< int >(),0)) << " negatives\n" ;

}

 

< 실행 결과 >

4 positives

3 negatives

 

 

그러면 「-3 이상, 3 미만의 요소 수」를 요구하려면 어떻게 할까요.

mid lo 이상, hi 미만이라면 true를 돌려준다

template <typename T>

bool in_between(T lo, T mid, T hi) {

return lo <= mid && mid < hi;

}

 

이런 함수 in_between 을 준비하여 제1인수를 -3, 3인수를 3으로 속박 하면 좋겠습니다만 표준 C++이 준비해 주고 있는 바인더(속박 함수) 2항 함수 오브젝트에 대한 bind1st bind2nd 뿐입니다.

TR1은 이와 같이 제한의 어려운 바인더를 일반 화해, operator() 에게 주는 임의의 인수를 속박 하는 범용 바인더 : bind 를 제공해 줍니다.

 

 

bind를 사용해 -3 이상, 3 미만의 요소를 센다

#include <iostream>

#include <algorithm>

#include <functional>

#include <boost/tr1/functional.hpp>

using namespace std;

 

// lo <= mid < hi 이라면 true를 돌려준다

template <typename T>

bool in_between(T lo, T mid, T hi) {

return lo <= mid && mid < hi;

}

 

int main()

{

const int N = 8;

int data[N] = { -3, -2, -1, 0, 1, 2, 3, 4 };

// 플레이스홀더: _1, _2, ... 를 유효하게 한다

using namespace tr1::placeholders;

// in_between의 제1,3인수를 각각 -3,3으로 속박 한다

cout << count_if(data, data+N,

tr1::bind(&in_between< int >, -3, _1, 3)) << " numbers are [-3,3)\n" ;

}


실행 결과

6 numbers are [-3,3)

 

 

플레이스홀더의 수/위치/순서는 자유롭게 선택할 수 있기 때문에 이하의 샘플과 같이 3항 함수의 인수 1개를 속박 해  2항 함수로 할 수도 있습니다.

 

요소의 소트

#include <iostream>

#include <algorithm>

#include <functional>

#include <boost/tr1/functional.hpp>

 

using namespace std;

 

// 오름/내림차순의 어느 쪽에도 사용할 수 있는 비교 함수

template <typename T>

bool compare(T x, T y, bool descend) {

return descend ? (x < y) : (y < x);

}

 

int main()

{

const int N = 8;

int data[N] = { 0, -1, 1, -2, 2, -3, 3, 4 };

using namespace tr1::placeholders;

// 내림차순로 소트sort의 제3인수는 2항 함수 오브젝트

sort(data, data+N, tr1::bind(&compare< int >, _1, _2, false ));

for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl;

// 승순으로 소트

sort(data, data+N, tr1::bind(&compare< int >, _1, _2, true ));

for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl;

// 이것도 역시 승순으로 소트(플레이스홀더의 순서에 주목)

sort(data, data+N, tr1::bind(&compare< int >, _2, _1, false ));

for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl;

}


실행 결과

4 3 2 1 0 -1 -2 -3-3 -2 -1 0 1 2 3 4-3 -2 -1 0 1 2 3 4

 

 

한층 더 bind 는 클래스의 멤버 함수마저도 바인드 해 줍니다.

 

멤버 함수의 바인드

#include <iostream>

#include <string>

#include <boost/tr1/functional.hpp>

 

using namespace std;

 

class Sandwitch {

string mid_;

public :

Sandwitch( const string& mid) : mid_(mid) {}

string make( const string& head, const string& tail) const {

return head + mid_ + tail;

}

};

 

int main()

{

Sandwich s( " and " );

Sandwich* p = &s;

using namespace tr1::placeholders;

// s.make("boys,"girls")

cout << tr1::bind(&Sandwich::make, s, "boys" , _1)( "girls" ) << endl;

// p->make("ladies","gentlemen")

cout << tr1::bind(&Sandwich::make, p, "ladies" , _1)( "gentlemen" ) << endl;

// p->make("black","white")

cout << tr1::bind(&Sandwich::make, p, _2, _1)( "while" ,"black" ) << endl;

// s.make("hit","away")

cout << tr1::bind(&Sandwich::make, _1, "hit" , "away" )(s) << endl;

// p->make("adam","eve");

cout << tr1::bind(&Sandwich::make, _1, "adam" , "eve" )(p) << endl;

// s.make("love","peace")

cout << tr1::bind(&Sandwich::make, _1, _2, _3)(s, "love" ,"peace" ) << endl;

}


실행 결과

boys and girls

ladies and gentlemen

black and while

hit and away

adam and eve

love and peace

 

 

출처 : http://codezine.jp/a/article/aid/2158.aspx

저작자 표시
신고
by 흥배 2010.03.15 08:30
| 1 |