Reputation: 20222
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
?
Upvotes: 3
Views: 117
Reputation: 20256
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).
Upvotes: 4
Reputation: 16421
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
.
Upvotes: 5