bsky
bsky

Reputation: 20222

Overloaded pointer to function

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

Answers (2)

Antonio
Antonio

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

krzaq
krzaq

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

Related Questions