7

can anyone tell me what is the mistake in this program

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    string str = "Now";

    transform(str.begin(), str.end(), str.begin(), toupper);

    cout<<str;

    return 0;
}

Error:

"no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'
compilation terminated due to -Wfatal-errors."
royhowie
  • 11,075
  • 14
  • 50
  • 67
user2413497
  • 211
  • 2
  • 3
  • 7

3 Answers3

12

There are two functions with name toupper. One from cctype header:

int toupper( int ch );

And second from locale header:

charT toupper( charT ch, const locale& loc );

Compiler can't deduce which function should be used, since you allow namespace std. You should use scope resolution operator(::) to choose function defined in global space:

transform(str.begin(), str.end(), str.begin(), ::toupper);

Or, better: Do not use using namespace std.


Thanks to @Praetorian -

This is probably the cause of the error, but adding :: may not always work. If you include cctype toupper is not guaranteed to exist in the global namespace. A cast can provide the necessary disambiguation static_cast<int(*)(int)>(std::toupper)

So, the call should look like:

std::transform
(
    str.begin(), str.end(),
    str.begin(),
    static_cast<int(*)(int)>(std::toupper)
);
awesoon
  • 32,469
  • 11
  • 74
  • 99
  • 1
    This is probably the cause of the error, but adding `::` may not always work. If you include *cctype* `toupper` is not guaranteed to exist in the global namespace. A cast can provide the necessary disambiguation `static_cast(std::toupper)` – Praetorian May 28 '13 at 13:05
3

In order to use toupper, you need to include header file:

#include <cctype>

You also need to include header file:

#include <string>

The problem is the std::toupper takes int as parameter, while std::transform will pass char into the function, therefore, it has a problem (by courtesy of @juanchopanza).

You may try to use:

 #include <functional>
 std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun<int, int>(std::toupper));

See example code from std::transform

Or you can implement your own toupper that takes char as argument.

taocp
  • 23,276
  • 10
  • 49
  • 62
  • I include but it is of no use – user2413497 May 28 '13 at 12:56
  • @user2413497 try to check the link I included? It has complete example at the bottom of the link with explanations. – taocp May 28 '13 at 12:57
  • @juanchopanza I agree. I will update the post now. – taocp May 28 '13 at 13:07
  • @juanchopanza, are you sure? Last argument for `std::transform` function is templated. `std::transform` doesn't care, accept it `int` or `char`. From cppreference: `The type Type must be such that an object of type InputIt can be dereferenced and then implicitly converted to Type. The type Ret must be such that an object of type OutputIt can be dereferenced and assigned a value of type Ret. ` – awesoon May 28 '13 at 13:25
  • @soon do you have a good explanation why it would not work with `std::toupper`? – juanchopanza May 28 '13 at 13:46
  • @juanchopanza, yes, I do. You could see it in my answer. In short: there are could be two reasons. First: compiler can't choose between `std::toupper` from `cctype` and `locale` headers. Second: `cctype` doesn't included, but `std::toupper` from `locale` is templated. Compiler cant infer template argument. – awesoon May 28 '13 at 13:56
  • @soon Yeah, you are right. In my test, the `` overload must have crept in, even if I didn't include ``. – juanchopanza May 28 '13 at 14:16
0

As the compiler has buried in its error message, the real problem is that toupper is an overloaded function, and the compiler can't figure out which one you want. There's the C toupper(int) function which may or may not be a macro (may not in C++, but does the C library care?), and there's std::toupper(char, locale) from (pulled in by without doubt), which you made available globally with your using namespace std;.

Tony's solution works because he accidentally resolved the overloading issue with his separate function.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157