A Correct and Portable Way
Fortunately, we can indeed get exactly the intended effect required by Question #3 in a completely type-safe and portable way, without relying on nonstandard code or type-unsafe casting. The way to do it is to use a proxy class that takes, and has an implicit conversion to, the desired pointer type:
Code:
// Example 3(d): The correct solution
//
struct FuncPtr_;
typedef FuncPtr_ (*FuncPtr)();
struct FuncPtr_
{
FuncPtr_( FuncPtr pp ) : p( pp ) { }
operator FuncPtr() { return p; }
FuncPtr p;
};
Now we can declare, define, and use f() naturally:
Code:
FuncPtr_ f() { return f; } // natural return syntax
int main()
{
FuncPtr p = f(); // natural usage syntax
p();
}
This solution has three main strengths:
1. It solves the problem as required. Better still, it's type-safe and portable.
2. Its machinery is transparent: You get natural syntax for the caller/user, and natural syntax for the function's own "return myname;" statement.
3. It probably has zero overhead: On modern compilers, the proxy class, with its storage and functions, should inline and optimize away to nothing.
Coda
Of course, normally a special-purpose FuncPtr_ proxy class like this (that contains some old object and doesn't really care much about its type) just cries out to be templatized into a general-purpose Holder proxy. Alas,
you can't just templatize the FuncPtr_ class above, because then the typedef would have to look something like:
typedef Holder<FuncPtr> (*FuncPtr)();
which is self-referential.