Reputation: 746
typedef std::vector<std::string> TVector;
TVector a_list;
populate vector...
for_each(a_list.begin(),a_list.end(),std::toupper);
error
no matching function for call to 'for_each(std::vector<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >::iterator, <unresolved overloaded function type>)
Do I need to iterate over the elements using the a standard for loop ? Or is there another way I am not allowed to use c++ 11 features.
Thanks
Upvotes: 3
Views: 1701
Reputation: 54971
std::toupper
is an overloaded function; that’s why you’re getting <unresolved overloaded function type>
in the error message. To select a particular overload, you need to cast it:
static_cast<int(*)(int)>(std::toupper)
for_each
is also not the right choice for this task—it will call toupper
for each string in the list, then discard the result. std::transform
would be the appropriate choice—it writes its output to an output iterator. However, toupper
works on characters, not strings. You could still use transform
to call toupper
for each character in a string:
std::transform(
a_string.begin(),
a_string.end(),
a_string.begin(),
static_cast<int(*)(int)>(std::toupper)
);
It would probably be clearer in this simple case to use loops:
for (TVector::iterator i = a_list.begin(), end = a_list.end(); i != end; ++i) {
for (std::string::size_type j = 0; j < i->size(); ++j) {
(*i)[j] = toupper((*i)[j]);
}
}
But if you wanted to write it with <algorithm>
and <iterator>
tools only, you could make a functor:
struct string_to_upper {
std::string operator()(const std::string& input) const {
std::string output;
std::transform(
input.begin(),
input.end(),
std::back_inserter(output),
static_cast<int(*)(int)>(std::toupper)
);
return output;
}
};
// ...
std::transform(
a_list.begin(),
a_list.end(),
a_list.begin(),
string_to_upper()
);
Upvotes: 2
Reputation: 409166
The toupper
function is used for characters, not strings. It also returns the uppercase character, so won't work with for_each
, but will with std::transform
. There is also the problem that std::toupper
exists in two overloads, and the compiler can't decide which one to use. Include <cctype>
and use plain toupper
(or optionally ::toupper
) to get the right function.
You need to iterate first over all strings in the vector, and the iterate again over the string to call toupper
.
You can either do it manually, or use transform
and use functor objects, something like
struct strtoupper
{
std::string operator()(const std::string& str) const
{
std::string upper;
std::transform(str.begin(), str.end(), std::back_inserter(upper), ::toupper);
return upper;
}
};
// ...
std::transform(a_list.begin(), a_list.end(), a_list.begin(), strtoupper());
Upvotes: 4
Reputation: 11232
You have a vector of std::string
and std::toupper
expects a char
as parameter. So it can not be used. What you can do is:
std::for_each(list.begin(), list.end(),[](std::string& s) { std::for_each(s.begin(), s.end(), std::toupper);});
Upvotes: 3