STL for_each жалуется на список аргументов - PullRequest
2 голосов
/ 20 января 2011

Как часть домашнего задания, мы должны отобразить вхождение каждого персонажа на карте. Наша функция должна использовать 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 *

Что я делаю не так?

Ответы [ 4 ]

6 голосов
/ 20 января 2011

CharStatistics::fillMap не является функцией, принимающей 1 аргумент. это функция-член и поэтому он имеет неявный первый аргумент - указатель на экземпляр класса.

в коде:

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

for_each не знаю, на какой экземпляр вы хотите позвонить CharStatistics::fillMap, вы не указали его. вам нужно привязать его к любому экземпляру CharStatistics, например ::10000

std::bind1st(std::mem_fun(&CharStatistics::fillMap), &char_statistics_instance)
2 голосов
/ 20 января 2011

document_ это набор символов?

Но эта функция является функцией-членом CharStatistics!Предположительно, вы вызываете это из функции-члена CharStatistics.В этом случае вы можете использовать boost :: bind, чтобы решить эту проблему, если это разрешено:

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

Вы можете использовать std :: bind1st для «this», что является более сложным, так как вам все еще нужен 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 есть ошибка.Решение, которое я дал, будет работать.

1 голос
/ 20 января 2011

По сути, неправильно то, что ваш контейнер имеет тип значения 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;
}
1 голос
/ 20 января 2011

Если 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), и экземпляр будет передан автоматически.

...