2010-12-10 9 views
0

std::vector<T>이 클래스의 일부이며 내 코드의 여러 다른 위치에서 반복해야하기 때문에 내가 될 것이라고 생각했습니다. 똑똑하고 IterateAttributes 함수를 만들고 루프에 넣고 단일 요소를 전달할 수있는 boost :: function 객체를 전달한 다음 요소에 대한 작업을 수행하는 함수를 전달할 수 있습니다.멤버를 반복하고 함수를 호출하여 함수를 호출 할 때 함수를 호출합니다.

구현하기 전까지는 좋은 생각 인 것 같습니다. 그런 다음 전달 된 함수에서 무엇이 반환되고 다른 인수가 필요한지 문제가 발생합니다. 템플릿을 사용하는 것과 같이 좀 더 일반적으로이를 수행하는 방법을 찾아야하거나 다른 args를 사용하는 함수 객체로 오버로드를 만들어야하는 것처럼 보입니다.

첫 번째 (더 일반적인) 옵션이 아마도 더 좋을 것이라고 생각하지만, 어떻게 생각 하나?

다음은 작동하지 않는 시험입니다. 그러나 많은 수의 args를 갖고 싶지만 Attribute (구조체) arg를 제외한 모든 arg는 필수입니다. 어떻게해야합니까?

template <typename T> template <typename arg> 
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_) 
{ 
    std::vector<Attribute>::iterator it = v_attributes.begin(); 

    for (; it != v_attributes.end(); it++) 
    { 
     func_(arg, *it); 
    } 
} 
+0

당신은'boost :: bind'를 사용하여 다른 인자들을 먼저 바인딩 한 다음'for_each'를 사용할 수 있습니다. (실제로 다른 함수를 쓸 필요가 있습니까?). 반환 값을 처리하는 것은 더 많은 생각이 필요합니다 .. – lijie

+0

@lijie : for_each는 반복되는 요소를 수정할 수 없다고 생각했습니다. –

+1

어 ... 나는 당신이 _collection_을 수정하지 말아야한다고 생각하지만, 요소 자체를 수정하는 것이 금지되어 있다고 생각하지 않습니다. (특히 vector와 같은 요소에 대해서는 요소의 순서가 중요하지 않습니다.) – lijie

답변

1

당신이 무슨 뜻인가요 :

모든 유형의 하나의 매개 변수를 허용
template <typename T, typename arg> 
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_, arg a) 
{ 
    std::vector<Attribute>::iterator it = v_attributes.begin(); 

    for (; it != v_attributes.end(); it++) 
    { 
     func_(a, *it); 
    } 
} 

- 당신은 당신이 더 많은 매개 변수도 버전을 소개 할 수 원하는 경우.

리턴 값에 대해 무엇을 할 것인가는 실제적으로 어떤 가치가 있는지에 따라 달라집니다. 일반적인 솔루션 (아마도 불필요한)은 std::list<T>을 반환 할 것이지만 그것이 해결할 수있는 것보다 많은 문제를 야기 할 것입니다.

빠른 해결 방법입니다
template <typename T> template <typename arg> 
void ElementNode::IterateAttributes(boost::function<voidT (arg, Attribute, T&)> func_) 
{ 
    std::vector<Attribute>::iterator it = v_attributes.begin(); 
    T result; 

    for (; it != v_attributes.end(); it++) 
    { 
     func_(arg, *it, result); 
    } 
    return result; 
} 

, 그것은 작동하지만 그건 : 반환 형식은 다음 (유형뿐만 아니라 의미뿐만 아니라) 변화하면 나는 그것이 전체 결과 및 업데이트를 적절하게 참조/포인터를 취 있도록 템플릿 기능을 modyfying 제안 추악하고, 오류가 발생하기 쉽고, 디버그하는 데 어려움이 있습니다. 당신이 변수 매개 변수의 양을 원하는 경우

는, 당신은 위의 함수의 여러 가지 템플릿을 만들 것 - 난 그냥 테스트가 가능하다면 :

template <typename T> 
T boo(T){ 

} 

template <typename T, typename TT> 
TT boo(T,TT){ 

} 

void test() 
{ 
    int i; 
    i= boo<int>(0); 
    i=boo<int,double>(0,0.0); 
} 

당신은 IterateAttributes 전달 기능을 exatly 주어진 매개 변수와 일치해야한다는 것을 기억해야한다 함수 반복. 그것은 또한 당신이 그것의 프로토 타입 디폴트 값을 사용할 수 없음을 의미합니다 - 아마 당신이

void func_(Attribute,arg1, arg2,arg3){...} 
void func_(Attribute A,arg1 a1,arg2 a2){func_(A,a1, a2,default3);} 
void func_(Attribute A,arg1 a1){func_(A,a1, default2,default3);} 
void func_(Attribute A){func_(A,default1, default2,default3);} 
+0

예, 그것이 내 뜻입니다. 일반 매개 변수를 더 많이 가질 수는 있지만 선택 사항입니까? 아니면 불가능한가요? –

+0

및 그다지 신속한 해결 방법이 없습니까? –

+0

"및 그다지 신속한 해결 방법이 없습니까?" - 당신이 그것을 완전히 일반화하고 싶다면, 템플릿이 결과가 무엇인지에 대해 어떤 가정도 할 수 없기 때문에 내가 보는 유일한 방법은 결과 목록을 반환하는 것입니다. 그렇지 않으면 다른 함수가 매개 변수와 hadling 결과로 전달 된 것으로 간주 할 수 있지만 매개 변수 목록을 확대하는 것은 원칙적으로 위의 해결 방법과 다릅니 다. 결과를 가지고 무엇을하고 싶은지 모른다면 (템플릿을 쓰는 단계에서) 어떻게하는지 말할 수는 없습니다. –

0

같은 몇 가지 오버로드 된 버전을 정의해야하는) 당신은 배열을 반복하고있다 각 요소에 뭔가를하고 싶지 :이 경우 , 당신은 모든 배열 요소를 취하고 void를 반환하는 함수를 원한다. 단순한.

b) 각 요소에 더 많은 인수가있는 함수를 부분적으로 적용하려면 다음과 같이하십시오. 추가로 미리 할당 된 인수를 저장하는 함수 주위에 사용자 지정 함수 작성기를 작성하거나 boost::bind을 사용하면 효과적으로 수행 할 수 있습니다.

예 :

vector<string> myStrings; // assign some values 

// define a function with an additional argument 
void myFunc(string message, string value) 
{ 
    cout << message << value << endl; 
} 

// allow partial application, i.e. "currying" 
struct local_function 
{ 
    static string message; 

    static void myFunc_Curried(string value) 
    { 
    myFunc(message, value); 
    }  
}; 

local_function::message = "the array contains: "; 

// apply the curried function on all elements in the array 
for_each(myStrings.begin(), myStrings.end(), local_function::myFunc_Curried); 

펑은 데모 용으로 정적으로 운영하고 있습니다. message이 구조체의 인스턴스에 바인드 된 경우 실제로는 카 트리트 함수를 호출하기 위해 this 인스턴스 포인터를 바인드하기 위해 boost::bind과 같은 것이 필요합니다.그러나 적용하려는 기능이 로컬에서만 사용되는 경우보다 읽기 쉬운 정적 접근 방식을 따르는 것이 좋습니다.

달성하고자하는 것은 매우 적합하며 기능 언어 (예 : F #)로 직접 작성됩니다. C++로는 가능하지만 앞에서 설명한 경우에는 몇 가지 해결 방법이 필요합니다. b. 제 예제에서와 같이 독자적인 펑터를 작성하는 경우, 처음부터 카레하게하려는 인수를 배치하고 부분적으로 적용 할 때 인수를 처음부터 끝까지 "채우는"것이 일반적이라는 점에 유의하십시오. 다음, 다른 인수를 결합 결과 펑터에 for_each를 사용하는

사용 bind : 의견 및 더 많은 생각을 요약

0

.

반환 값을 처리하려면 반환 값의 의미를 고려해야합니다. 어떤 방법으로 값을 사용해야하는 경우 (예 : 축소 작업을 수행하거나 작업 수행을 계속할지 여부 등을 결정하는 데 사용), 다른 펑터를 사용하여 원본을 래핑하여 원하는 작업을 수행 할 수 있습니다 .

0

BOOST_FOREACH 또는 C++ 0x for each을 사용하여 동일 또는 그 이상의 작업을 수행 할 수 있습니다. 그러면 작성하는 코드가 적어집니다.

관련 문제