2

宿題の一環として、マップ内の各文字の出現をマップすることになっています。この関数は、std :: 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であり、私の関数はcharを受け入れます。イテレータは他の何物でもありませんchar *

私は何が間違っているのですか?

4

4 に答える 4

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)
于 2011-01-20T12:01:35.567 に答える
2

document_ は文字のコレクションですか?

しかし、関数は CharStatistics のメンバ関数です! おそらく、CharStatistics のメンバー関数からこれを呼び出していると思われます。その場合、許可されている場合は boost::bind を使用して解決できます。

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

「this」で std::bind1st を使用できますが、これは mem_fun が必要なため、より複雑です。

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 関数にエラーがあることに注意してください。私が与えた解決策は機能します。

于 2011-01-20T12:06:26.233 に答える
1

が静的メンバー関数でない場合CharStatistics::fillMapは、呼び出しをインスタンスにバインドする必要があります。

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

さらに、静的メンバー関数でない場合、実際には 2 つの引数があります。1 つ目は暗黙のthisポインターで、2 つ目はchar. boost::bindしたがって、次を使用して(またはstd::bindC++0x を使用している場合)、2 つの引数をバインドする必要があります。

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

for_eachbind2ndこれで、インスタンスが 1 つの引数 ( ) を受け取る関数オブジェクトとして表示され、_1インスタンスが自動的に渡されます。

于 2011-01-20T12:04:35.157 に答える
1

基本的に何が間違っているかというと、あなたのコンテナは値 type を持っていて、 の引数を取る関数を期待していcharますが、 のインスタンスを取る関数オブジェクトに評価されます(その上で を呼び出します) 。for_eachcharstd::mem_fun(&CharStatistics::fillMap)CharStatisticsfillMap

単純に関数を変更してみませんか:

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;
}
于 2011-01-20T12:09:41.053 に答える