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