Template substitution for function parameters

Biotronic via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Sep 3 16:32:35 PDT 2017


On Saturday, 2 September 2017 at 01:41:14 UTC, Nicholas Wilson 
wrote:
> On Friday, 1 September 2017 at 11:33:15 UTC, Biotronic wrote:
>> On Friday, 1 September 2017 at 10:15:09 UTC, Nicholas Wilson 
>> wrote:
>>> So I have the following types
>>>
>>> struct DevicePointer(T) { T* ptr; }
>>>
>>> struct Buffer(T)
>>> {
>>>     void* driverObject;
>>>     T[] hostMemory;
>>> }
>>>
>>> and a function
>>>
>>> auto enqueue(alias k)(HostArgsOf!k) { ... }
>>>
>>> where k would be a function like
>>>
>>> void foo( DevicePointer!float a, float b , int c) { ... }
>>>
>>> How can I write HostArgsOf such that HostArgsOf!foo yields:
>>> AliasSeq!(Buffer!float, float, int)
>>> preferably in such a way that I can add additional 
>>> transformations to it later on?
>>>
>>> i.e. it substitutes the template DevicePointer for the 
>>> template Buffer in Parameters!foo,
>>> The templates can be assumed to not be nested templates, i.e. 
>>> DevicePointer!(DevicePointer!(float)) will never occur 
>>> neither will Buffer!(Buffer!(float) or any cross templates)
>>
>> template k(alias fn) {
>>     import std.meta, std.traits;
>>     alias k = staticMap!(ReplaceTemplate!(DevicePointer, 
>> Buffer), Parameters!fn);
>> }
>>
>> template ReplaceTemplate(alias needle, alias replacement) {
>>     template ReplaceTemplate(alias T) {
>>         static if (is(T : needle!Args, Args...)) {
>>             alias ReplaceTemplate = replacement!Args;
>>         } else {
>>             alias ReplaceTemplate = T;
>>         }
>>     }
>> }
>
> Hmm, it seems I oversimplified the example a bit and this 
> doesn't quite work for my actual usecase.
>
> struct DevicePointer(int n,T) { T* ptr; }
>
> alias GlobalPointer(T) = DevicePointer!(1,T);
>
> k!foo yields
> DevicePointer!(cast(AddrSpace)1u, float), float, int
> instead of
> Buffer!float, float, int
>
> I think because the is(T : needle!Args, Args...) fails.

It really shouldn't work at all - the is(T : ...) works great, 
but gives Args as (1, float), and fails to instantiate Buffer 
with those arguments. This should give a compilation error.

Anyways, updated code that should work:

     template ReplaceTemplate(alias needle, alias replacement) {
         template ReplaceTemplate(alias T) {
             static if (is(T : needle!Args, Args...)) {
                 alias ReplaceTemplate = replacement!(Args[1]);
             } else {
                 alias ReplaceTemplate = T;
             }
         }
     }

If you only ever use this for DevicePointer and Buffer, a less 
generic solution might be more understandable for maintainers:

     template ReplaceDevicePointer(alias T) {
         static if (is(T : DevicePointer!(n, T), int n, T)) {
             alias ReplaceDevicePointer = Buffer!T;
         } else {
             alias ReplaceDevicePointer = T;
         }
     }

--
   Biotronic


More information about the Digitalmars-d-learn mailing list