2011-01-20 2 views
2

숙제의 일부로지도의 각 문자 발생을 매핑해야합니다. 우리 함수는 std :: for_each를 사용하여 평가할 문자를 전달해야합니다.STL for_each가 인수 목록에 대해 불평 함

std::for_each(document_.begin(), 
       document_.end(), 
       std::mem_fun(&CharStatistics::fillMap)); 

document_string이며, fillMap 기능은 std::map<char, unsigned int> chars_;로 선언

void CharStatistics::fillMap(char ch) 
{ 
    ch = tolower(ch); 
    ++chars_.find(ch)->second; 
} 

chars_과 같이 정의된다 :

내 기능입니다.

나는이 일을해야 내려고하지만, 컴파일러는 내가 인수 목록

_Fn1=std::mem_fun1_t<void,CharStatistics,char>, 
1>   _Elem=char, 
1>   _Traits=std::char_traits<char>, 
1>   _Alloc=std::allocator<char>, 
1>   _Result=void, 
1>   _Ty=CharStatistics, 
1>   _Arg=char, 
1>   _InIt=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>> 

가 나에게 잘 보이는 볼 때 때문에, 저를 혼란

error C2064: term does not evaluate to a function taking 1 arguments 

불평한다. _Elem은 char이고 my 함수는 char을 허용합니다. 이터레이터는 A 이외에는 없습니다. char *

내가 뭘 잘못하고 있니?

답변

6

CharStatistics::fillMap은 1 개의 인수를 취하는 함수가 아닙니다. 그것은 멤버 함수이므로 암시적인 첫 번째 인수 - 클래스 인스턴스에 대한 포인터가 있습니다. 코드에서

:

std::for_each(document_.begin(), 
       document_.end(), 
       std::mem_fun(&CharStatistics::fillMap)); 

for_each 당신이 CharStatistics::fillMap를 호출하고 싶은 경우에 모르는 , 당신이 그것을 지정하지 않았습니다. 당신이 어떤 CharStatistics 인스턴스에 바인딩해야합니다 예 :

CharStatistics instance; 
std::for_each(
    document_.begin(), 
    document_.end(), 
    std::bind1st(
     &CharStatistics::fillMap, 
     &instance 
    ) 
); 

을 또한, 인 경우에 : 정적 멤버 함수가 아닌

std::bind1st(std::mem_fun(&CharStatistics::fillMap), &char_statistics_instance) 
1

CharStatistics::fillMap 경우에, 당신은 인스턴스에 전화를 바인드해야 정적 구성원 함수가 아니라면 실제로 두 개의 인수가 있습니다. 첫 번째 포인터는 암시적인 this 포인터이고 두 번째 포인터는 char입니다.

CharStatistics instance; 
std::for_each(
    document_.begin(), 
    document_.end(), 
    boost::bind(
     &CharStatistics::fillMap, 
     &instance, 
     _1 
    ) 
); 

for_each 지금은 하나 개의 인자 (_1)를 복용하는 함수 객체로 bind2nd 인스턴스를 참조해야하며 : 그래서 당신이 (당신이 C++ 0X에있는 경우 또는 std::bind) boost::bind를 사용하여, 두 개의 인수를 결합해야 인스턴스가 자동으로 전달됩니다.

+0

bind2nd는 당신이 쓴 것은 부스트 ​​:: 바인드 또는 표준 : : 바인드 (새로운 표준) 건설이다, 그렇게하지 것이다. bind2nd는 함수와 매개 변수라는 두 개의 매개 변수 만 사용하기 때문에 컴파일러 오류가 발생합니다. – CashCow

+0

@CashCow : 아, 당신 말이 맞아요. 나는 항상 boost :: bind를 사용한다. 편집 됨. –

2

document_는 문자 모음입니까?

그러나이 함수는 CharStatistics의 멤버 함수입니다! 아마도 CharStatistics의 멤버 함수에서 이것을 호출하고있을 것입니다.그이 허용되는 경우이 경우 당신이 부스트를 사용할 수 있습니다 :: 바인드 그것을 해결하기 위해 :

std::for_each(document_.begin(), document_.end(), 
    boost::bind(&CharStatistics::fillMap, this, _1); 

당신은 여전히 ​​mem_fun을 필요로하는 더 복잡 "이"있는 표준 : : bind1st를 사용할 수

std::for_each(document_.begin(), document_.end(), 
     std::bind1st(std::mem_fun(&CharStatistics::fillMap), this)); 

실제로 끔찍하게보기가 복잡합니다. 이것이 새로운 바인딩이 훨씬 더 나은 이유입니다!

boost :: bind를 사용할 수없고 mem_fun 솔루션이 마음에 들지 않으면 operator()에 과부하가 걸린 펑터를 작성하십시오. 이처럼 : 루프 호출

std::for_each(document_.begin(), document_.end(), CharStatsFunctor(chars_)); 

주에서

struct CharStatsFunctor 
{ 
    typedef std::map< char, size_t > map_type; 
    map_type & mapToFill; 
    explicit CharStatsFunctor(map_type & m) : mapToFill(m) {} 

    void operator()(char ch) const 
    { 
     ++mapToFill[ ::tolower(ch) ]; 
    } 
}; 

당신의 fillMap 기능에 오류가 있습니다. 내가 준 해결책이 효과가있다.

+0

+1 ... 나는 거의 독점적으로 그러한 작업을 위해 펑터를 사용합니다. 그들은 훨씬 더 고통스럽지 않습니다. –

1

기본적으로 무엇을 잘못하면 컨테이너가 값 형식 char을 가지고 있으며, for_eachchar의 인수를 취하는 함수를 기대하고 있지만, std::mem_fun(&CharStatistics::fillMap)는 (있는 그 다음 호출 CharStatistics의 인스턴스를받는 함수 객체로 평가 fillMap)

이유는 단순히 기능을 변경하지 :

void CharStatistics::fillMap(std::string const& str) 
{ 
    std::string::const_iterator it(str.begin()), end(str.end()); 
    for(; it != end; ++it) 
    ++chars_.find(tolower(*it))->second; 
}