On Tue, Jul 07, 2015 at 07:54:18PM +0000, jmh530 via Digitalmars-d-learn wrote: > I'm not sure I understand the safety of function pointers vs. the addresses > of functions. The code below illustrates the issue.
Function pointers and addresses of functions are the same thing. There is no difference between them. > I was under the impression that pointers are not allowed in safe code. This is incorrect. Pointers are allowed in safe code as long as they are not manipulated in unsafe ways (e.g., assigning a literal value to them, pointer arithmetic, casting to a pointer to an incompatible type, using a pointer to call an un-@safe function from @safe code, etc.). > Naturally, I took that to also mean that function pointers are not > allowed in safe code. Indeed, I haven't been able to pass a function > pointer to a safe function. However, I am able to take the address of > a function and pass that as a parameter. It seems to work fine for > taking the address of functions and templates (so long as I !) The reason for this is that function pointers have attributes associated with them, as part of the type system. The address of a @safe function is a @safe function pointer, meaning that it's legal to call the function through this pointer in @safe code. The address of a @system function is a @system function pointer, which *cannot* be used to call the function from @safe code. However, while it is not allowed to assign a @system function pointer to a @safe function pointer (since that could be used to bypass the @safe restriction on calling @system functions), it is OK to assign a @safe function pointer to a @system function pointer (this is called covariance). This is allowed because a @system function pointer can only be dereferenced in @system code, and @system code can freely call any function with no restrictions. Where this might become a problem, though, is when you inadvertently assign a @safe function pointer to a @system function pointer, and then attempt to call it from @safe code -- the compiler will reject that. This is what happened with your sample code: [...] > void main() > { > function_safety(&cbrt); //prints fp is trusted > real function(real) fp = &cbrt; Here, fp is a @system function pointer. While &cbrt is a @safe function pointer, it is covariant with a @system function pointer, so the assignment is allowed. > function_safety(fp); //prints fp is system [...] The result, however, is now @system, so you can no longer call cbrt from @safe code through this particular function pointer (though you can obviously call it through a @safe function pointer). The correct syntax for declaring a @safe function pointer would be: real function(real) @safe fp = ...; Either that, or use `auto` to let the compiler figure out the correct function pointer attributes for you: auto fp = &cbrt; pragma(msg, typeof(fp).stringof); The compiler prints: real function(real x) nothrow @nogc @trusted So you see here that two other attributes, nothrow and @nogc, are also inferred by the compiler, which is a good thing because otherwise your function pointer wouldn't be usable from nothrow or @nogc code, respectively. T -- Music critic: "That's an imitation fugue!"