2010-01-20 3 views
3

this 질문에 대한 첫 번째 대답에 따르면, 아래의 펑터는 foreach으로 전달 된 후에 값을 유지할 수 있어야합니다 (이 예에서는 컴파일 할 때 struct Accumulator을 얻을 수 없어 클래스가 작성되었습니다).함수는 std :: for_each에 전달 될 때 값을 유지할 수 있습니까?

// Using a functor 
Accumulator acc; 
std::for_each(_cards.begin(), _cards.end(), acc); 
// according to the example - acc.counter contains the sum of all 
// elements of the deque 

std::cout << acc.counter << std::endl; 

_cards (예 당)

class Accumulator 
{ 
    public: 
     Accumulator(): counter(0){} 
     int counter; 
     void operator()(const Card & c) { counter += i; } 
}; 

사용 예는 std::deque<Card>로서 구현된다. _cards이 얼마나 길어도 for_each이 완료되면 acc.counter은 0입니다. 내가 디버거에서 단계별로 카운터 증가를 볼 수 있지만, 그래서 그것은 값으로 전달되는 acc과 관련이 있습니까?

+0

간단한 개념으로 카운터를 사용하여 개념을 설명했습니다. 사실 내가 원하는 것은'faceup'과'facedown' 값을 유지하는 것입니다. 즉, deque를 반복하고 deque의 각 카드를 쿼리하여 얼굴 수를 위아래로 유지하는 것입니다. – BeeBand

+0

Functor에서 정적 변수를 사용하는 것은 어떻습니까? – ALOToverflow

+0

안녕하세요. 그것의 동일한 질문 http://stackoverflow.com/questions/2102056/foreach-doesnt-this-work-as-int –

답변

6

이 단지 asked here이었다 다음과 같이

은 누적를 수정합니다.

이유는 (추측에 따라) std::for_each은 해당 기능을 복사하고 호출합니다. 그러나, 또한 그것을 반환하므로 위의 대답에 요약 된대로 for_each의 반환 값을 사용하십시오. 말했다

, 당신은 단지 std::accumulate를 사용해야합니다 :

int counter = std::accumulate(_cards.begin(), _cards.end(), 0); 

펑터와 for_each 여기에 수정되지 않습니다. 사용량에 대한


, 당신은 아마도 자신의 펑를 제공하고 count_if 사용해야합니다 (다른 사람을 무시하고 일부 계산) :

// unary_function lives in <functional> 
struct is_face_up : std::unary_function<const Card&, const bool> 
{ 
    const bool operator()(const card& pC) const 
    { 
     return pC.isFaceUp(); // obviously I'm guessing 
    } 
}; 

int faceUp = std::count_if(_cards.begin(), _cards.end(), is_face_up()); 
int faceDown = 52 - faceUp; 

을 그리고와 C++ 0X 람다의 재미를 위해 (단지 왜냐하면 :

int faceUp = std::count_if(_cards.begin(), _cards.end(), 
          [](const Card& pC){ return pC.isFaceUp(); }); 

훨씬 좋네요.

+0

감사. 이제 행복해?! :-) 그런데'faceup'과'facedown'에 관한 위의 코멘트는 for_each에 대한 필요성을 여전히 무효로합니까? 나는'std :: accumulate'이 내가 뭘하는지에 대해 생각하지 않는다. – BeeBand

+0

아니, 맞아. 그러나 귀하의 경우 카운트는'std :: pair ' – MSalters

3

네, 확실히 가치에 의해 전달되는 것과 관련이 있습니다.

class Accumulator 
{ 
    public: 
     Accumulator(): counter(new int(0)){} 
     boost::shared_ptr<int> counter; 
     void operator()(int i) { *counter += i; } 

     int value() { return *counter; } 
}; 
+0

Ew, 힙 할당 그냥 결과를 얻을? – GManNickG

+1

@GMan : 예. 나는'std :: for_each'가 거의 반 패턴 인 것으로 결론을 내 렸습니다. 유용한 것으로 보이지만 거의 모든 경우에 그것을 사용하는 것이 비생산적입니다. –

+0

@ 제리 : 어느 정도 동의합니다. 직접 손으로 작업하는 것이 더 많은 일입니다. 다행스럽게도 람다는'for_each'를 가장 많이 사용되는 알고리즘 중 하나라고 생각합니다. – GManNickG

3

이것은 내부적으로 std :: for_each()가 임시 객체를 전달할 수 있기 때문에 펑터 사본을 만들기 때문입니다. 그래서 내부적으로 당신이 제공 한 객체가 아닌 사본의 합계를 수행합니다.

좋은 소식은 std :: for_each()가 거기에서 액세스 할 수 있도록 결과로 Functor 복사본을 반환한다는 것입니다.

참고 : 사용할 수있는 다른 표준 알고리즘이 있습니다. std :: accumulate()와 같습니다.
그러나이 예제는 단순화 된 예제이며 for_each()가 예제보다 약간 더 복잡해 졌다고 가정하면 누산기 오브젝트에 액세스 할 수있는 몇 가지 기술이 있습니다.

#include <iostream> 
#include <algorithm> 
#include <vector> 

class Card{ public: int i;}; 
class Accumulator 
{ 
    public: 
     Accumulator(): counter(0){} 
     int counter; 
     void operator()(const Card & c) { counter += c.i; } 
}; 


int main() 
{ 
    std::vector<Card> cards; 

    Accumulator a = std::for_each(cards.begin(), cards.end(), Accumulator()); 

    std::cout << a.counter << std::endl; 

} 

또는 현재 범위 내에서 사용되는 참조를 증가 시키도록 Accumalator를 변경할 수 있습니다.

#include <iostream> 
#include <algorithm> 
#include <vector> 

class Card{ public: int i;}; 
class Accumulator 
{ 
     int& counter; 
    public: 
     // Pass a reference to constructor. 
     // Copy construction will pass this correctly into the internal object used by for_each 
     Accumulator(int& counterRef): counter(counterRef){} 
     void operator()(const Card & c) { counter += c.i; } 
}; 


int main() 
{ 
    std::vector<Card> cards; 

    int counter = 0; // Count stored here. 

    std::for_each(cards.begin(), cards.end(), Accumulator(counter)); 

    std::cout << counter << std::endl; 

} 
+0

될 것입니다. 각 반복에 대한 복사는 아마 과장된 것입니다. 그것은 단지 값으로 술어를 취하는데, 유일하게 생각할 수있는 다른 대안은 const 참조에 의해 받아 들여지고 있습니다. 여전히이 사용법을 허용하지 않을 것입니다 (비 const 연산자()). – UncleBens

+0

@UncleBens, yes, debug는 기본 ctor가 일단 호출되면 (Accumulator acc 선언을 가정 함),'_cards.size()'에 상관없이 Copy Ctor가 두 번 호출됨을 보여줍니다. – BeeBand

+0

Missworded. 올바른 것입니다. –

관련 문제