www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP Mir1 Draft: Variadic template parameters with the same time.

reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
Problem

Most ndslice API accepts variadic list of integers.
The following code example shows how `slice` and `[a, b, c]`
can generate 64 identical functions each.

```
// (1, 1U, 1UL, 1L) x
// (2, 2U, 2UL, 2L) x
// (3, 3U, 3UL, 3L) = 4 ^^ 3 = 64 identical variants
auto cube = slice!double(1, 2, 3);

size_t i;
sizediff_t j;
int k;
uint p;
// 64 identical variants for 64-bit with i, j, k, p
auto v = cube[i, j, k];
```
------------------------

Solution

T[] can be added to a template variadic name.

```
void foo(size_t[] Index...)(Indexes index)
{
     ...
}
```
Sep 29 2016
next sibling parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
https://github.com/libmir/mir/wiki/Compiler-and-druntime-bugs#dips
Sep 29 2016
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 29 September 2016 at 17:24:55 UTC, Ilya Yaroshenko 
wrote:
 Problem

 Most ndslice API accepts variadic list of integers.
 The following code example shows how `slice` and `[a, b, c]`
 can generate 64 identical functions each.

 ```
 // (1, 1U, 1UL, 1L) x
 // (2, 2U, 2UL, 2L) x
 // (3, 3U, 3UL, 3L) = 4 ^^ 3 = 64 identical variants
 auto cube = slice!double(1, 2, 3);

 size_t i;
 sizediff_t j;
 int k;
 uint p;
 // 64 identical variants for 64-bit with i, j, k, p
 auto v = cube[i, j, k];
 ```
 ------------------------

 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
Sep 29 2016
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 29 September 2016 at 18:37:36 UTC, Ilya Yaroshenko 
wrote:
 On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch 
 wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
I think we already have typesafe variadics. What do you want to change ?
Sep 29 2016
next sibling parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 18:49:45 UTC, Stefan Koch wrote:
 On Thursday, 29 September 2016 at 18:37:36 UTC, Ilya Yaroshenko 
 wrote:
 On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch 
 wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
I think we already have typesafe variadics.
Only for runtime arguments.
 What do you want to change ?
`(Index...)` -> `(size_t[] Index...)` // this is about template arguments, not runtime
Sep 29 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 09/29/2016 02:53 PM, Ilya Yaroshenko wrote:
 `(Index...)` -> `(size_t[] Index...)` // this is about template
 arguments, not runtime
What is the drawback of taking Index... and constraining it with a template constraint (all must be integral)? We use that in a few places in Phobos. -- Andrei
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 18:55:07 UTC, Andrei 
Alexandrescu wrote:
 On 09/29/2016 02:53 PM, Ilya Yaroshenko wrote:
 `(Index...)` -> `(size_t[] Index...)` // this is about template
 arguments, not runtime
What is the drawback of taking Index... and constraining it with a template constraint (all must be integral)? We use that in a few places in Phobos. -- Andrei
This is the same like in current ndslice code. For 3D cube[i, j, k] 64(!) templates can be generated because each of i, j, k can be int, uint, size_t, sizediff_t.
Sep 29 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:
 On Thursday, 29 September 2016 at 18:55:07 UTC, Andrei 
 Alexandrescu wrote:
 On 09/29/2016 02:53 PM, Ilya Yaroshenko wrote:
 `(Index...)` -> `(size_t[] Index...)` // this is about template
 arguments, not runtime
What is the drawback of taking Index... and constraining it with a template constraint (all must be integral)? We use that in a few places in Phobos. -- Andrei
This is the same like in current ndslice code. For 3D cube[i, j, k] 64(!) templates can be generated because each of i, j, k can be int, uint, size_t, sizediff_t.
Yah, I remember. Can you experiment with arranging things such that all templates forward to the same backend function that does the work?
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei 
Alexandrescu wrote:
 Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:
 On Thursday, 29 September 2016 at 18:55:07 UTC, Andrei 
 Alexandrescu wrote:
 On 09/29/2016 02:53 PM, Ilya Yaroshenko wrote:
 `(Index...)` -> `(size_t[] Index...)` // this is about 
 template
 arguments, not runtime
What is the drawback of taking Index... and constraining it with a template constraint (all must be integral)? We use that in a few places in Phobos. -- Andrei
This is the same like in current ndslice code. For 3D cube[i, j, k] 64(!) templates can be generated because each of i, j, k can be int, uint, size_t, sizediff_t.
Yah, I remember. Can you experiment with arranging things such that all templates forward to the same backend function that does the work?
This already done. But anyway lot of template bloat would note disappeared. In addition there are inlining and mapSlice
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 20:54:12 UTC, Ilya Yaroshenko 
wrote:
 On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei 
 Alexandrescu wrote:
 Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:
 On Thursday, 29 September 2016 at 18:55:07 UTC, Andrei 
 Alexandrescu wrote:
 [...]
This is the same like in current ndslice code. For 3D cube[i, j, k] 64(!) templates can be generated because each of i, j, k can be int, uint, size_t, sizediff_t.
Yah, I remember. Can you experiment with arranging things such that all templates forward to the same backend function that does the work?
This already done. But anyway lot of template bloat would note disappeared. In addition there are inlining and mapSlice
I am sorry for my terrible English (i am in a dark room now)
Sep 29 2016
parent reply Timothee Cour via Digitalmars-d <digitalmars-d puremagic.com> writes:
this works:

void foo(T, size_t n)(T[n] a ...) {...}

However, see this: https://github.com/libmir/mir/issues/337


On Thu, Sep 29, 2016 at 1:57 PM, Ilya Yaroshenko via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 20:54:12 UTC, Ilya Yaroshenko wrote:

 On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei Alexandrescu wrote:

 Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:

 On Thursday, 29 September 2016 at 18:55:07 UTC, Andrei Alexandrescu
 wrote:

 [...]
This is the same like in current ndslice code. For 3D cube[i, j, k] 64(!) templates can be generated because each of i, j, k can be int, uint, size_t, sizediff_t.
Yah, I remember. Can you experiment with arranging things such that all templates forward to the same backend function that does the work?
This already done. But anyway lot of template bloat would note disappeared. In addition there are inlining and mapSlice
I am sorry for my terrible English (i am in a dark room now)
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 21:06:13 UTC, Timothee Cour 
wrote:
 this works:

 void foo(T, size_t n)(T[n] a ...) {...}

 However, see this: https://github.com/libmir/mir/issues/337


 On Thu, Sep 29, 2016 at 1:57 PM, Ilya Yaroshenko via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 20:54:12 UTC, Ilya 
 Yaroshenko wrote:

 On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei 
 Alexandrescu wrote:

 Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:

[...]
Yah, I remember. Can you experiment with arranging things such that all templates forward to the same backend function that does the work?
This already done. But anyway lot of template bloat would note disappeared. In addition there are inlining and mapSlice
I am sorry for my terrible English (i am in a dark room now)
Thanks! ag0aep6g have suggested the same. I am confused that I did know this solution. Will open separate thread for https://github.com/libmir/mir/issues/337.
Sep 29 2016
parent reply Timothee Cour via Digitalmars-d <digitalmars-d puremagic.com> writes:
maybe remove the corresponding DIP from
https://github.com/libmir/mir/wiki/Compiler-and-druntime-bugs#dips ?

On Thu, Sep 29, 2016 at 2:19 PM, Ilya Yaroshenko via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 21:06:13 UTC, Timothee Cour wrote:

 this works:

 void foo(T, size_t n)(T[n] a ...) {...}

 However, see this: https://github.com/libmir/mir/issues/337


 On Thu, Sep 29, 2016 at 1:57 PM, Ilya Yaroshenko via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 20:54:12 UTC, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei Alexandrescu
 wrote:

 Ilya Yaroshenko <ilyayaroshenko gmail.com> wrote:
 [...]

 Yah, I remember. Can you experiment with arranging things such that
 all templates forward to the same backend function that does the work?
This already done. But anyway lot of template bloat would note disappeared. In addition there are inlining and mapSlice
I am sorry for my terrible English (i am in a dark room now)
Thanks! ag0aep6g have suggested the same. I am confused that I did know this solution. Will open separate thread for https://github.com/libmir/mir/issues/337.
Sep 29 2016
parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 21:31:11 UTC, Timothee Cour 
wrote:
 maybe remove the corresponding DIP from 
 https://github.com/libmir/mir/wiki/Compiler-and-druntime-bugs#dips ?

 On Thu, Sep 29, 2016 at 2:19 PM, Ilya Yaroshenko via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 21:06:13 UTC, Timothee Cour 
 wrote:

 this works:

 void foo(T, size_t n)(T[n] a ...) {...}

 However, see this: https://github.com/libmir/mir/issues/337


 On Thu, Sep 29, 2016 at 1:57 PM, Ilya Yaroshenko via 
 Digitalmars-d < digitalmars-d puremagic.com> wrote:

 On Thursday, 29 September 2016 at 20:54:12 UTC, Ilya 
 Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:47:35 UTC, Andrei 
 Alexandrescu
[...]
I am sorry for my terrible English (i am in a dark room now)
Thanks! ag0aep6g have suggested the same. I am confused that I did know this solution. Will open separate thread for https://github.com/libmir/mir/issues/337.
Just found an example, where this approach does not work :-( template transposed(Dimensions...) if (Dimensions.length) { Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice) { ... } }
Sep 29 2016
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/29/16 2:49 PM, Stefan Koch wrote:
 On Thursday, 29 September 2016 at 18:37:36 UTC, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
I think we already have typesafe variadics. What do you want to change ?
typesafe variadics as runtime parameters, not compile-time parameters. -Steve
Sep 29 2016
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 09/29/2016 02:37 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
This feature exists. What am I missing? -- Andrei
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 18:53:26 UTC, Andrei 
Alexandrescu wrote:
 On 09/29/2016 02:37 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 17:56:59 UTC, Stefan Koch 
 wrote:
 Solution

 T[] can be added to a template variadic name.

 ```
 void foo(size_t[] Index...)(Indexes index)
 {
     ...
 }
 ```
This description does not tell me anything.
Current template argument can be declared as `(Index...)`. The solutions just allows to specify the type `(size_t[] Index...)`
This feature exists. What am I missing? -- Andrei
No, it does not --- , void foo(size_t[] I...)(I i) { } void main() { foo(1, 2, 3); } --- /d812/f719.d(1): Error: found '...' when expecting ')' /d812/f719.d(1): Error: found ')' when expecting '(' /d812/f719.d(1): Error: basic type expected, not ( /d812/f719.d(1): Error: function declaration without return type. (Note that constructors are always named 'this') /d812/f719.d(2): Error: found '{' when expecting ')' /d812/f719.d(4): Error: semicolon expected following function declaration /d812/f719.d(4): Error: unrecognized declaration
Sep 29 2016
next sibling parent reply pineapple <meapineapple gmail.com> writes:
On Thursday, 29 September 2016 at 18:56:40 UTC, Ilya Yaroshenko 
wrote:
 No, it does not
 ---
 void foo(size_t[] I...)(I i)
 {
 	
 }
Using phobos' allSatisfy or a similar template, this can become: enum isIndex(T) = is(T == size_t); void foo(I...)(I i) if(allSatisfy!(isIndex, I)){ ... }
Sep 29 2016
parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 19:03:00 UTC, pineapple wrote:
 On Thursday, 29 September 2016 at 18:56:40 UTC, Ilya Yaroshenko 
 wrote:
 No, it does not
 ---
 void foo(size_t[] I...)(I i)
 {
 	
 }
Using phobos' allSatisfy or a similar template, this can become: enum isIndex(T) = is(T == size_t); void foo(I...)(I i) if(allSatisfy!(isIndex, I)){ ... }
would not work: auto v = cube[1, 2, 3];
Sep 29 2016
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Here's one way to do it:
------
import core.stdc.stdio;

void foo(T)(T[] a ...)
{
     printf("%d %d %d\n", a[0], a[1], a[2]);
}

void main()
{
     foo(1, 2, 3);
}
-----
C:\cbx>foo
1 2 3
Sep 29 2016
parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 20:12:44 UTC, Walter Bright 
wrote:
 Here's one way to do it:
 ------
 import core.stdc.stdio;

 void foo(T)(T[] a ...)
 {
     printf("%d %d %d\n", a[0], a[1], a[2]);
 }

 void main()
 {
     foo(1, 2, 3);
 }
 -----
 C:\cbx>foo
 1 2 3
a.length must be known at CT. 99%-100% foreach loops in ndslice package are CT.
Sep 29 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 09/29/2016 10:43 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:12:44 UTC, Walter Bright wrote:
[...]
 void foo(T)(T[] a ...)
 {
     printf("%d %d %d\n", a[0], a[1], a[2]);
 }
[...]
 a.length must be known at CT. 99%-100% foreach loops in ndslice package
 are CT.
I'm not sure if I understand the goal, but what about this: void foo(size_t n)(size_t[n] a ...) { /* ... */ }
Sep 29 2016
next sibling parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 20:57:00 UTC, ag0aep6g wrote:
 On 09/29/2016 10:43 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:12:44 UTC, Walter Bright 
 wrote:
[...]
 void foo(T)(T[] a ...)
 {
     printf("%d %d %d\n", a[0], a[1], a[2]);
 }
[...]
 a.length must be known at CT. 99%-100% foreach loops in 
 ndslice package
 are CT.
I'm not sure if I understand the goal, but what about this: void foo(size_t n)(size_t[n] a ...) { /* ... */ }
YES! Many Thanks! This is what i need!
Sep 29 2016
prev sibling parent reply Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 20:57:00 UTC, ag0aep6g wrote:
 On 09/29/2016 10:43 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:12:44 UTC, Walter Bright 
 wrote:
[...]
 void foo(T)(T[] a ...)
 {
     printf("%d %d %d\n", a[0], a[1], a[2]);
 }
[...]
 a.length must be known at CT. 99%-100% foreach loops in 
 ndslice package
 are CT.
I'm not sure if I understand the goal, but what about this: void foo(size_t n)(size_t[n] a ...) { /* ... */ }
Just found an example, where this approach does not work :-( template transposed(Dimensions...) if (Dimensions.length) { Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice) { ... } }
Sep 29 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 09/29/2016 11:28 PM, Ilya Yaroshenko wrote:
 On Thursday, 29 September 2016 at 20:57:00 UTC, ag0aep6g wrote:
[...]
 void foo(size_t n)(size_t[n] a ...) { /* ... */ }
Just found an example, where this approach does not work :-( template transposed(Dimensions...) if (Dimensions.length) { Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice) { ... } }
When the values themselves are known at compile time, we can convert them to size_t before generating the function: ---- enum isIndex(T) = is(T == size_t); /* by pineapple */ enum asIndex(size_t value) = value; template transposed(Dimensions...) if (Dimensions.length) { import std.meta: allSatisfy, staticMap; static if (allSatisfy!(isIndex, typeof(Dimensions))) { void transposed() {} /* simplified for the example */ } else { alias transposed = transposed!(staticMap!(asIndex, Dimensions)); } } alias t1 = transposed!(1, 2, 3); alias t2 = transposed!(1LU, 2LU, 3LU); static assert(&t1 == &t2); /* passes */ ----
Sep 29 2016
parent Ilya Yaroshenko <ilyayaroshenko gmail.com> writes:
On Thursday, 29 September 2016 at 22:03:36 UTC, ag0aep6g wrote:
 On 09/29/2016 11:28 PM, Ilya Yaroshenko wrote:
 [...]
[...]
 [...]
When the values themselves are known at compile time, we can convert them to size_t before generating the function: ---- enum isIndex(T) = is(T == size_t); /* by pineapple */ enum asIndex(size_t value) = value; template transposed(Dimensions...) if (Dimensions.length) { import std.meta: allSatisfy, staticMap; static if (allSatisfy!(isIndex, typeof(Dimensions))) { void transposed() {} /* simplified for the example */ } else { alias transposed = transposed!(staticMap!(asIndex, Dimensions)); } } alias t1 = transposed!(1, 2, 3); alias t2 = transposed!(1LU, 2LU, 3LU); static assert(&t1 == &t2); /* passes */ ----
Thanks again!
Sep 29 2016