STL for_each жалуется на список аргументов
Как часть домашнего задания, мы должны составить карту вхождения каждого персонажа в карту. Наша функция должна использовать 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 ответа
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)
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 есть ошибка. Решение, которое я дал, будет работать.
По сути, неправильно то, что ваш контейнер имеет тип значения 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;
}
Если 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
), и экземпляр будет передан автоматически.