2

作为家庭作业的一部分,我们应该在地图中映射每个字符的出现。我们的函数应该使用 std::for_each 并传入要评估的字符。

我的功能是:

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

document_是 a 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 *

我究竟做错了什么?

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() 以获取字符。像这样:

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

此外,如果它不是静态成员函数,那么它实际上有两个参数。第一个是隐式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) 的函数对象,并且该实例将自动传递。

于 2011-01-20T12:04:35.157 回答
1

基本上错误的是你的容器有一个值类型char,并且for_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;
}
于 2011-01-20T12:09:41.053 回答