3

I was looking over the following code:

string toUpper(string s) {
    string result;
    int (*toupperp)(int) = &toupper; // toupper is overloaded
    transform(begin(s), end(s), back_inserter(result), toupperp);
    return result;
}

I am confused by this line:

int (*toupperp)(int) = &toupper; // toupper is overloaded

1.Why is this line necessary?

2.I believe that & retrieves a pointer to something from memory. But toupper, the name of the function is already a pointer, no? Why can't we do this:

int (*toupperp)(int) = toupper;

3.Why is the function overloaded to int if it's used on a string?

bsky
  • 19,326
  • 49
  • 155
  • 270

2 Answers2

5

1) It's not necessary, really. If you have used using namespace std directive, it's necessary to cast to the desired type to let the compiler know which overload you want. So, you might also say

transform(begin(s), end(s), back_inserter(result), static_cast<int(*)(int)>(&toupper));

Otherwise the following should be enough:

transform(begin(s), end(s), back_inserter(result), ::toupper);

2) Identifiers that are function names decay into pointers, yes, but they aren't exactly the same thing. That being said, in this case it should be fine to say

int (*toupperp)(int) = toupper;

or even (if you haven't used using namespace std directive):

auto toupperp = toupper; 

3) it's for compatibility with C standard library. It's used on every element of s, which for string is a char.

Community
  • 1
  • 1
krzaq
  • 16,240
  • 4
  • 46
  • 61
  • I think [`toupper`](http://www.cplusplus.com/reference/cctype/toupper/) has no overload, does it? – Antonio Oct 24 '16 at 11:38
  • @Antonio good point for clarification. `::toupper` is not overloaded, but `std::toupper` is - look up in [``](http://en.cppreference.com/w/cpp/locale/toupper) – krzaq Oct 24 '16 at 11:39
  • There's also a [very interesting comment](http://stackoverflow.com/questions/2942426/how-do-i-specify-a-pointer-to-an-overloaded-function/2942442#comment7190884_2942442) on why using the intermediate variable is preferable, I learnt something today – Antonio Oct 24 '16 at 11:42
  • @Antonio that comment is not right for `static_cast`. Both are the same conversions and both are compile-time errors if there's no such overload. – krzaq Oct 24 '16 at 11:45
4

What you are passing to transform is a pointer to the function toupper (see function pointers). You store this pointer into the local variable toupperp. The type of toupperp is a pointer to a function taking an int as argument and returning an int.

Unless toupper is defined in strange ways, the function is seemingly used by transform to change each input character to uppercase. Each single character is processed as an integer (with an implicit cast if needed).

Regarding your question 2, using the operator & you make more explicit you are taking the address of the function, but indeed you could omit it. See here (I learnt something today).

If toupper was overloaded, using the intermediate variable is a safe way to get exactly the desired overload. If the desired overload goes away this method will catch the problem at compile time. See here. (And that's something else I learnt today).

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197