Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
September 01, 2017 Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
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) |
September 01, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Friday, 1 September 2017 at 10:15:09 UTC, Nicholas Wilson wrote:
> So I have the following types
> ...
> 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)
Wow, this Question triggers an immediate headache...What about this ?
import std.traits: Parameters;
alias HostArgsOf(alias A) = AliasSeq!(Parameters!A[0], Parameters!A[1], Parameters!A[2]);
|
September 01, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to user1234 | On Friday, 1 September 2017 at 10:58:51 UTC, user1234 wrote:
> On Friday, 1 September 2017 at 10:15:09 UTC, Nicholas Wilson wrote:
>> So I have the following types
>> ...
>> 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)
>
> Wow, this Question triggers an immediate headache...What about this ?
>
> import std.traits: Parameters;
> alias HostArgsOf(alias A) = AliasSeq!(Parameters!A[0], Parameters!A[1], Parameters!A[2]);
It will probably take the form
alias HostArgsOf(alias k) = staticMap!(something, Parameters!k);
I'm just not sure how to formulate the something.
|
September 01, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | 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; } } } |
September 01, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Biotronic | 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;
> }
> }
> }
Thanks!
|
September 02, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Biotronic | 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. |
September 03, 2017 Re: Template substitution for function parameters | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | 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
|
Copyright © 1999-2021 by the D Language Foundation