www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Explicit cast to system?

reply Anonymouse <zorael gmail.com> writes:
I have some nested templated code that takes function pointers. 
In many cases I pass it functions of identical signatures, except 
some are ` safe` and others are ` system`. In those cases the 
templates end up getting instantiated twice. I don't care about 
the ` safe`-ness and I'd really like to just have them all 
treated as ` system`, with one instantiation per unique signature.

To illustrate:

```
void foo(F)(F fun)
{
     pragma(msg, F.stringof);
}

void bar()  safe {}
void baz()  system {}

void main()
{
     foo(&bar);
     foo(&baz);
}
```

Outputs:

```
void function()  safe
void function()
```

I *can* do this by explicitly passing the type as a template 
parameter;

```
void main()
{
     foo!(void function()  system)(&bar);
     foo(&baz);
}
```

...but there are a lot of different signatures and I need a 
general approach. There doesn't seem to be such a thing as 
`cast( system)fp`.

My current solution involves some very gnarly string mixins.

```
static if (F.stringof.indexOf(" safe") != -1)
{
     mixin("alias SystemF = " ~ F.stringof.replace(" safe", 
" system") ~ ";");
}
else
{
     alias SystemF = F;
}
```

...where `F` is `void function()`, ` safe` or ` system`. Then I 
can explicitly pass `SystemF` as a compile-time parameter, and I 
get my decreased instantiations.

But surely there has to be a better way?
Oct 08 2022
next sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Saturday, 8 October 2022 at 23:06:13 UTC, Anonymouse wrote:
 I have some nested templated code that takes function pointers. 
 In many cases I pass it functions of identical signatures, 
 except some are ` safe` and others are ` system`. In those 
 cases the templates end up getting instantiated twice. I don't 
 care about the ` safe`-ness and I'd really like to just have 
 them all treated as ` system`, with one instantiation per 
 unique signature.
 ...
 But surely there has to be a better way?
You might be templating more information than necessary. In your example `foo` doesn't need to be a template at all: ```D void foo(void function() system fun) { pragma(msg, typeof(fun).stringof); } ``` If your real code needs to template the return type and parameters of `fun`, for example, consider just templating those instead of the whole function pointer type: ```D void foo(R, P...)(R function(P) system fun) { pragma(msg, typeof(fun).stringof); } ``` (Things do get awkward with `ref` and `out`, though, because D considers them to be part of the function's type rather than part of the parameter or return types. `ref` is the bane of my D meta-programming existence.)
Oct 09 2022
parent Anonymouse <zorael gmail.com> writes:
On Sunday, 9 October 2022 at 16:25:22 UTC, tsbockman wrote:
 You might be templating more information than necessary. In 
 your example `foo` doesn't need to be a template at all:
 ```D
 void foo(void function()  system fun) {
     pragma(msg, typeof(fun).stringof);
 }
 ```
Yes, it was a toy example. It's complicated and I need crayons to explain it well, but the real code is a nested function in a main function in a template mixin, mixed into a class in a module dedicated to it. When invoked the main function introspects module-level functions annotated with particular UDAs and calls them -- or doesn't, depending on other factors. Several modules (grep says 23) then each have their own class types that mix in this mixin, and each module's module-level functions take that module's class as parameter. Like the hello world example does [here](https://github.com/zorael/kameloso/blob/a471a33/source/kameloso/plugins/hello.d#L17-L25). So the `__FUNCTION__` string of one instance of the nested function could be (and note the ` safe`): ``` kameloso.plugins.notes.NotesPlugin.IRCPluginImpl!(Flag.no, "kameloso.plugins.notes").onEventImpl.process!(false, false, void function(NotesPlugin, ref const(IRCEvent)) safe).process ``` Even if I somehow manage to change the nested `process` to not be a template I still need to instantiate the housing `IRCPluginImpl` mixin once per class (and module), so I'm not sure. I could just annotate everything ` system` too.
Oct 09 2022
prev sibling parent reply user1234 <user1234 12.de> writes:
On Saturday, 8 October 2022 at 23:06:13 UTC, Anonymouse wrote:
 I have some nested templated code that takes function pointers. 
 In many cases I pass it functions of identical signatures, 
 except some are ` safe` and others are ` system`. In those 
 cases the templates end up getting instantiated twice. I don't 
 care about the ` safe`-ness and I'd really like to just have 
 them all treated as ` system`, with one instantiation per 
 unique signature.

 To illustrate:

 [...]

 ...but there are a lot of different signatures and I need a 
 general approach. There doesn't seem to be such a thing as 
 `cast( system)fp`.

 My current solution involves some very gnarly string mixins.
I see what you mean, in the past I wanted `cast(pure)`, `cast(nothrow)`, similarly to avoid using metaprog (or maybe was that delegates) in certain case.
 [...]
 But surely there has to be a better way?
No.
Oct 09 2022
parent Anonymouse <zorael gmail.com> writes:
On Sunday, 9 October 2022 at 17:42:57 UTC, user1234 wrote:
 But surely there has to be a better way?
No.
Darn. Okay, thanks.
Oct 09 2022