2011-09-12 8 views
24

을 사용하면 결과로 나타나는 에 바인드 된 객체가 예상하는 것보다 많은 인수가 수신 될 수 있습니다. 개념적 : 그 서명은 인수가없는 것을 나타내는 경우에도boost :: bind를 사용하여 예상보다 많은 인수를 안전하게 전달합니까?

int func() { return 42; } 
boost::function<int (int,int,int)> boundFunc = boost::bind(&func); 
int answer = boundFunc(1,2,3); 

이 경우 func() 스택에 1, 2, 3을 수신한다.

이 값이 적은 인수를 사용하지만, 결합 객체를 호출 할 때 인수의 정확한 수를 공급하는 boost::function 항복 특정 개체 고정 partial application 대한 boost::bind의 전형적인 사용 다르다.

다음 코드는 MSVC++ 2010 SP1과 함께 작동합니다. 게시 할 양식이 줄어 듭니다. 원래 코드는 Linux의 g ++ 4.4에서도 작동합니다.

다음은 C++ 표준에 따라 잘 정의되어 있습니까?

#include <iostream> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

using namespace std; 

void func1(int x) { std::cout << "func1(" << x << ")\n"; } // end func1() 

void func0() { std::cout << "func0()\n"; } // end func0() 

int main(int argc,char* argv[]) 
{ 
     typedef boost::function<void (int)> OneArgFunc; 
     OneArgFunc oneArg = boost::bind(&func1,_1); 
     // here we bind a function that accepts no arguments 
     OneArgFunc zeroArg = boost::bind(&func0); 
     oneArg(42); 
     // here we invoke a function that takes no arguments 
     // with an argument. 
     zeroArg(42); 

    return 0; 
} // end main() 

내가 왜 zeroArg(42) 작품을 이해 : 사용되지 않는 인수는 호출 된 루틴에 의해 호출 루틴에 의해 스택에 넣어 간단하게 액세스 할 수 없습니다. 호출 된 루틴이 반환되면 호출 루틴은 스택을 정리합니다. 인수를 스택에 넣었으므로 인수를 제거하는 방법을 알고 있습니다.

다른 아키텍처 또는 컴파일러로 이동하면이 문제가 해결됩니까? 보다 적극적인 최적화가 이것을 깨뜨릴 것입니까?


나는 Boost 문서 또는 표준 문서에서 더 강력한 성명서를 찾고 있습니다. 나는 어느 쪽이든 모호하지 않은 위치를 찾을 수 없었다.

디버거를 사용하여 어셈블리와 스택을 살펴보면 첫 번째 예제의 func에 값 1,2와 3이 표시되지 않는다는 것을 알 수 있습니다. 앞에서 올바른 것입니다. 두 번째 예의 func0에 대해서도 마찬가지입니다. 적어도 필자가보고있는 구현 인 MSVC++ 2010SP1 및 g ++ 4.4/Linux의 경우에도 마찬가지입니다. 마지막 예에서, 함수 객체에 의해 생성 된 것을

bind(f, _2, _1)(x, y);     // f(y, x) 

bind(g, _1, 9, _1)(x);     // g(x, 9, x) 

bind(g, _3, _3, _3)(x, y, z);   // g(z, z, z) 

bind(g, _1, _1, _1)(x, y, z);   // g(x, x, x) 

참고 : 나는 그것을 추가 인수를 전달하는 안전하다는 것을 싶습니다 참조 부스트 설명서를 보면

, 그것은 분명하지 않다 bind(g, _1, _1, _1)에는 첫 번째 인수 이외의 인수에 대한 참조가 들어 있지 않지만 두 개 이상의 인수와 함께 계속 사용될 수 있습니다. 첫 번째와 두 번째 인수가 세 번째 예제에서 무시되는 것처럼 추가 인수는 자동으로 무시됩니다. [강조 광산.]

문 추가 인수에 대한 무시는 나는 이것이 일반적인 경우에 사실 저를 설득 원하는만큼 명확하지 않다. TR1에서, 호출 가능 객체 return from bind 대상 객체 expects와 다른 수의 인수로 호출 될 수 있다는 것을 3.6.3 절에서 알 수 있습니다.그게 최선의 보장을 사용할 수 있습니까?

+5

+1 완벽한 첫 번째 질문입니다. 나는 너를 조금 사랑해. –

답변

14

예, 이것은 the documentation에서 명시 적으로 언급 한 것처럼 안전하고 이식성이 뛰어납니다. boost::bind에 의해 반환 된 bind-expression은 추가 인수를 자동으로 무시합니다.

즉, 첫 번째 예에서 func가하는 하지

는 값 1, 23boundFunc이 값 1, 23를 수신하고 안전하게 수신 포함 된 바인딩 표현,로 전달받을 이를 무시한 다음 func()을 호출합니다. 마찬가지로 두 번째 예에서 zeroArg은 값 42을 받고 포함 된 바인드 표현식으로 전달합니다. 포함 된 바인드 표현식은 값을 받고 무시하며 func0()을 호출합니다.

+3

실제로. 'func()'는 마술처럼 예상보다 많은 호출 객체를받지 못한다. 'boost :: bind' (중개 함수, 정말로)는 그것들을 받아들입니다. (그리고 그것도 괜찮습니다.) 그리고 나서 단지 그들을 최종적인 피 호출자에게 전달하지 않습니다. –

+0

디버거를 사용하여 어셈블리와 스택을 살펴보면 첫번째 예제의'func'는 값 1,2와 3을받지 못합니다. 적어도 필자가보고있는 구현은 MSVC++ 2010SP1 및 g ++ 4.4/Linux입니다. –