Re: Template substitution for function parameters

2017-09-03 Thread Biotronic via Digitalmars-d-learn
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


Re: Template substitution for function parameters

2017-09-01 Thread Nicholas Wilson via Digitalmars-d-learn

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.


Re: Template substitution for function parameters

2017-09-01 Thread Nicholas Wilson via Digitalmars-d-learn

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!


Re: Template substitution for function parameters

2017-09-01 Thread Biotronic via Digitalmars-d-learn
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;
}
}
}


Re: Template substitution for function parameters

2017-09-01 Thread Nicholas Wilson via Digitalmars-d-learn

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.




Re: Template substitution for function parameters

2017-09-01 Thread user1234 via Digitalmars-d-learn
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]);


Template substitution for function parameters

2017-09-01 Thread Nicholas Wilson via Digitalmars-d-learn

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)