2011-01-20 78 views
2

作爲家庭作業的一部分,我們應該映射地圖中每個角色的出現。我們的函數應該使用std :: for_each並傳入要評估的字符。STL for_each抱怨參數列表

我的功能是:

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

document_string,並且fillMap函數的定義如下

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

chars_被聲明爲std::map<char, unsigned int> chars_;

我想這應該工作,但是編譯器抱怨

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

這讓我困惑,因爲當我看着參數列表

_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>> 

它看起來好像沒什麼問題。 _Elem是一個字符,我的函數接受一個字符。迭代器只是一個char *

我在做什麼錯?

回答

6

CharStatistics::fillMap不是一個帶1個參數的函數。它是成員函數,所以它有隱含的第一個參數 - 指向類實例的指針。

代碼:

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

for_each不知道你想上哪個實例調用CharStatistics::fillMap,你沒有指定。你需要任何CharStatistics實例綁定它,例如:

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

如果CharStatistics::fillMap不是一個靜態成員函數,那麼你需要調用綁定到一個實例:

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

此外,如果它是不是一個靜態成員函數,那麼它實際上有兩個參數。第一個是隱含的this指針,第二個是char。所以,你必須綁定兩個參數,使用boost::bind(或std::bind如果你在的C++ 0x):

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

for_each現在應該看到bind2nd實例作爲帶一個參數(_1)函數對象,以及實例會自動傳遞。

+0

bind2nd不會那麼做的,你寫的是一個boost ::綁定或std ::綁定(新標準)建造。你將得到一個編譯器錯誤,因爲bind2nd只接受2個參數,一個函數和一個參數。 – CashCow 2011-01-20 12:19:07

+0

@CashCow:啊,你說得對。我總是使用`boost :: bind`。編輯。 – 2011-01-20 12:21:05

2

document_是字符集合嗎?

但是該函數是CharStatistics的成員函數!大概你是從CharStatistics的成員函數調用它。在這種情況下,你可以使用boost ::綁定來解決這個問題,如果被允許:

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

你可以在「此」,這是更爲複雜,因爲你仍然需要mem_fun使用std :: bind1st

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

這實際上是非常複雜的外觀。這就是爲什麼新綁定更好!

如果你不允許使用boost :: bind,並且你不喜歡mem_fun解決方案,那麼編寫你自己的函子來重載operator()來獲取char。就像這樣:

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) ]; 
    } 
}; 

在循環調用

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

注有你fillMap功能的錯誤。我給出的解決方案將工作。

1

基本上什麼是錯的是你的容器具有價值型charfor_each需要一個函數,它接受的char的說法,但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; 
}