Thread overview
How to attach function attributes to delegate type?
Feb 27, 2019
Q. Schroll
Feb 27, 2019
Alex
Mar 01, 2019
Vijay Nayar
February 27, 2019
For any type constructors like const, I can use ConstOf!T to get `T` with const attached. For a delegate/function type DG, e.g. int delegate(int), how can I get the @safe version of that type, i.e. int delegate(int) @safe?

I tried

    alias SafeOf(DG) = DG @safe;

but it didn't compile.

The case is not @safe-specific; it's the same for all function attributes.
February 27, 2019
On Wednesday, 27 February 2019 at 20:03:15 UTC, Q. Schroll wrote:
> For any type constructors like const, I can use ConstOf!T to get `T` with const attached. For a delegate/function type DG, e.g. int delegate(int), how can I get the @safe version of that type, i.e. int delegate(int) @safe?
>
> I tried
>
>     alias SafeOf(DG) = DG @safe;
>
> but it didn't compile.
>
> The case is not @safe-specific; it's the same for all function attributes.

At https://p0nce.github.io/d-idioms/

there is a demonstration for @nogc:

´´´
import std.traits;

// Casts @nogc out of a function or delegate type.
auto assumeNoGC(T) (T t) if (isFunctionPointer!T || isDelegate!T)
{
    enum attrs = functionAttributes!T | FunctionAttribute.nogc;
    return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
}
´´´

Didn't try this for other cases, however...
March 01, 2019
On Wednesday, 27 February 2019 at 20:45:33 UTC, Alex wrote:
> On Wednesday, 27 February 2019 at 20:03:15 UTC, Q. Schroll wrote:
>> For any type constructors like const, I can use ConstOf!T to get `T` with const attached. For a delegate/function type DG, e.g. int delegate(int), how can I get the @safe version of that type, i.e. int delegate(int) @safe?
>>
>> I tried
>>
>>     alias SafeOf(DG) = DG @safe;
>>
>> but it didn't compile.
>>
>> The case is not @safe-specific; it's the same for all function attributes.
>
> At https://p0nce.github.io/d-idioms/
>
> there is a demonstration for @nogc:
>
> ´´´
> import std.traits;
>
> // Casts @nogc out of a function or delegate type.
> auto assumeNoGC(T) (T t) if (isFunctionPointer!T || isDelegate!T)
> {
>     enum attrs = functionAttributes!T | FunctionAttribute.nogc;
>     return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
> }
> ´´´
>
> Didn't try this for other cases, however...

When I need particular attributes, such as for a comparator, but also need to pass in a function as a template argument, one approach I've started to adopt is to only call this function from within a wrapper that has all the properties I want.

For example:

import std.stdio;

class MyThing(T, alias LessF) {
  // This wrapper defines the conditions for a valid LessF.
  @safe @nogc
  private static bool less(in T t1, in T t2) {
    return LessF(t1, t2);
  }
}

void main()
{
  MyThing!(int, (a, b) => a < b) a;  // Compiles fine!
  MyThing!(int, (a, b) {
    writeln("Not @nogc!");  // Compiler error!
    return a < b;
  }) b;
}

The error looks like this, which is fairly readable too.

onlineapp.d(6): Error: `@nogc` function `onlineapp.main.MyThing!(int, (a, b)
{
writeln("Not @nogc!");
return a < b;
}
).MyThing.less` cannot call non-@nogc function