digitalmars.D.learn - Chain two different struct specialization
- Andrea Fontana (16/16) Mar 01 2013 I'm trying to do something like this. I don't know whether or not
- Andrea Fontana (32/48) Mar 01 2013 Ops. Here the complete message:
- bearophile (5/6) Mar 01 2013 ==>
- Andrea Fontana (40/46) Mar 01 2013 Sure not the only error. I was writing "pseudo code". Real code
- bearophile (32/34) Mar 01 2013 One solution is to not use templates:
- bearophile (4/10) Mar 01 2013 Sorry for the mix of tabs and spaces. The crappy editor I have
- Andrea Fontana (8/19) Mar 01 2013 That's right.
- bearophile (38/42) Mar 01 2013 firstWeights and secondWeights are compile-time constants, but
- Andrea Fontana (9/54) Mar 01 2013 but:
- bearophile (8/16) Mar 01 2013 Right.
- Era Scarecrow (28/48) Mar 01 2013 With templates there's a few different ways you can consider
- Andrea Fontana (11/62) Mar 01 2013 Maybe if i have MyStruct!Weights1 arr[]; MyStruct!Weights2
I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions struct MyStruct(WEIGHTS) { string ... string ... alias WEIGHTS weights; } double likeness(T,T1)(ref in T1, ref in T2) { // Here i do some complex calculus using struct fields // and using weights consts } enum FirstWeights : double { }
Mar 01 2013
On Friday, 1 March 2013 at 14:27:40 UTC, Andrea Fontana wrote:I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions struct MyStruct(WEIGHTS) { string ... string ... alias WEIGHTS weights; } double likeness(T,T1)(ref in T1, ref in T2) { // Here i do some complex calculus using struct fields // and using weights consts } enum FirstWeights : double { }Ops. Here the complete message: I'm trying to do something like this. I don't know whether or not it's a good idea, i'm open to solutions and suggestions struct MyStruct(WEIGHTS) { string ... string ... alias WEIGHTS weights; } double likeness(T,T1)(ref in T1, ref in T2) { // Here i do some complex calculus using struct fields // and using weights consts } enum FirstWeights : double { double foo = 0.3, double bar = 0.4 } enum SecondWeights : double { double foo = 0.3, double bar = 0.4 } so: auto s1 = MyStruct!FirstWeights ... auto s2 = MyStruct!SecondWeights ... likeness(s1,s2); // works But I can't mix different type (s1,s2) on a single range or array, to check for likeness, is there a way? (or should I avoid template init a double[] weights field)
Mar 01 2013
Andrea Fontana:double likeness(T,T1)(ref in T1, ref in T2)==> double likeness(T1, T2)(in ref T1, in ref T2) Bye, bearophile
Mar 01 2013
On Friday, 1 March 2013 at 14:39:53 UTC, bearophile wrote:Andrea Fontana:Sure not the only error. I was writing "pseudo code". Real code it's quite complex. Try this one (is a really reduced working example): struct MyStruct(WEIGHTS) { this (int p, int p2) { prop = p; prop2 = p2; } int prop; int prop2; alias WEIGHTS weights; } double likeness(T1,T2)(ref in T1 first, ref in T2 second) { double v = (first.prop - second.prop) * first.weights.foo * second.weights.foo; v += (first.prop2 - second.prop2) * first.weights.bar * second.weights.bar; return v; } enum FirstWeights : double { foo = 0.3, bar = 0.4 } enum SecondWeights : double { foo = 0.5, bar = 0.2 } void main(string[] args) { auto s1 = MyStruct!FirstWeights(10,8); auto s2 = MyStruct!FirstWeights(9, 10); auto s3 = MyStruct!SecondWeights(9,10); writeln(likeness(s1,s2)); // works writeln(likeness(s1,s3)); // works } How to put s1,s2,3... in a range/array or something similar/iterable? Probably there's no way (inside variant?)...double likeness(T,T1)(ref in T1, ref in T2)==> double likeness(T1, T2)(in ref T1, in ref T2) Bye, bearophile
Mar 01 2013
Andrea Fontana:How to put s1,s2,3... in a range/array or something similar/iterable? Probably there's no way (inside variant?)...One solution is to not use templates: immutable struct Weights { double foo, bar; } enum Weights firstWeights = { foo: 0.3, bar: 0.4 }, secondWeights = { foo: 0.5, bar: 0.2 }; struct MyStruct { int prop, prop2; immutable Weights weights; this ( Weights weights_, in int p, in int p2) pure nothrow { prop = p; prop2 = p2; } } double likeness(in ref MyStruct first, in ref MyStruct second) { double v = (first.prop - second.prop) * first.weights.foo * second.weights.foo; return v + (first.prop2 - second.prop2) * first.weights.bar * second.weights.bar; } void main() { immutable s1 = MyStruct(firstWeights, 10, 8); immutable s2 = MyStruct(firstWeights, 9, 10); immutable s3 = MyStruct(secondWeights, 9, 10); import std.stdio; writeln(likeness(s1, s2)); writeln(likeness(s1, s3)); const r = [s1, s2, s3]; } Bye, bearophile
Mar 01 2013
void main() { immutable s1 = MyStruct(firstWeights, 10, 8); immutable s2 = MyStruct(firstWeights, 9, 10); immutable s3 = MyStruct(secondWeights, 9, 10); import std.stdio; writeln(likeness(s1, s2));Sorry for the mix of tabs and spaces. The crappy editor I have used now has not replaced your tabs with spaces... Bye, bearophile
Mar 01 2013
On Friday, 1 March 2013 at 15:08:21 UTC, bearophile wrote:That's right. I think you missed an initialization on this(): I fixed it. BTW, compiler can't guess s1 and s2 weights, should it? if inside likeness() i write: enum test = first.weights.foo * second.weights.foo; it said that can't read first and second value at compile time. Andreavoid main() { immutable s1 = MyStruct(firstWeights, 10, 8); immutable s2 = MyStruct(firstWeights, 9, 10); immutable s3 = MyStruct(secondWeights, 9, 10); import std.stdio; writeln(likeness(s1, s2));Sorry for the mix of tabs and spaces. The crappy editor I have used now has not replaced your tabs with spaces... Bye, bearophile
Mar 01 2013
Andrea Fontana:BTW, compiler can't guess s1 and s2 weights, should it? if inside likeness() i write: enum test = first.weights.foo * second.weights.foo; it said that can't read first and second value at compile time.firstWeights and secondWeights are compile-time constants, but the arguments you give to likeness are run-time values, so they are unknown at compile-time inside likeness. There are ways to solve that problem, but I don't know how much good this is: immutable struct Weights { double foo, bar; } enum Weights firstWeights = { foo: 0.3, bar: 0.4 }, secondWeights = { foo: 0.5, bar: 0.2 }; struct MyStruct { int prop, prop2; immutable Weights weights; this(Weights weights_, in int p, in int p2) pure nothrow { this.weights = weights_; this.prop = p; this.prop2 = p2; } } double likeness(alias first, alias second)() { enum test = first.weights.foo * second.weights.foo; double v = (first.prop - second.prop) * first.weights.foo * second.weights.foo; return v + (first.prop2 - second.prop2) * first.weights.bar * second.weights.bar; } void main() { enum s1 = MyStruct(firstWeights, 10, 8); enum s2 = MyStruct(firstWeights, 9, 10); enum s3 = MyStruct(secondWeights, 9, 10); import std.stdio; writeln(likeness!(s1, s2)()); writeln(likeness!(s1, s3)()); const r = [s1, s2, s3]; } Bye, bearophile
Mar 01 2013
On Friday, 1 March 2013 at 16:03:58 UTC, bearophile wrote:Andrea Fontana:but: enum s1 = MyStruct(firstWeights, 10, 8); enum s2 = MyStruct(firstWeights, 9, 10); writeln(likeness(s1, s2)); still gives error: and s1 and s2 are known at compile time, aren't them? Your solution will create code for each item couple, isn't it? Not good in my case :) Other ideas?BTW, compiler can't guess s1 and s2 weights, should it? if inside likeness() i write: enum test = first.weights.foo * second.weights.foo; it said that can't read first and second value at compile time.firstWeights and secondWeights are compile-time constants, but the arguments you give to likeness are run-time values, so they are unknown at compile-time inside likeness. There are ways to solve that problem, but I don't know how much good this is: immutable struct Weights { double foo, bar; } enum Weights firstWeights = { foo: 0.3, bar: 0.4 }, secondWeights = { foo: 0.5, bar: 0.2 }; struct MyStruct { int prop, prop2; immutable Weights weights; this(Weights weights_, in int p, in int p2) pure nothrow { this.weights = weights_; this.prop = p; this.prop2 = p2; } } double likeness(alias first, alias second)() { enum test = first.weights.foo * second.weights.foo; double v = (first.prop - second.prop) * first.weights.foo * second.weights.foo; return v + (first.prop2 - second.prop2) * first.weights.bar * second.weights.bar; } void main() { enum s1 = MyStruct(firstWeights, 10, 8); enum s2 = MyStruct(firstWeights, 9, 10); enum s3 = MyStruct(secondWeights, 9, 10); import std.stdio; writeln(likeness!(s1, s2)()); writeln(likeness!(s1, s3)()); const r = [s1, s2, s3]; } Bye, bearophile
Mar 01 2013
Andrea Fontana:but: enum s1 = MyStruct(firstWeights, 10, 8); enum s2 = MyStruct(firstWeights, 9, 10); writeln(likeness(s1, s2)); still gives error: and s1 and s2 are known at compile time, aren't them?Right. But they are known at compile-time only outside likeness().Your solution will create code for each item couple, isn't it?Right.Not good in my case :) Other ideas?Another solution is to use indirection, with classes or unsafe casts. Or to use variants. No solution is perfect. Why do you want to perform those computations at compile-time? Bye, bearophile
Mar 01 2013
On Friday, 1 March 2013 at 14:32:12 UTC, Andrea Fontana wrote:struct MyStruct(WEIGHTS) { string ... string ... alias WEIGHTS weights; }With templates there's a few different ways you can consider handling it; I'm not recommending any of them but. Keeping it simple, clean & easy to read is probably the best solution; Although most of these won't help with any algorithms that need them to be identical (unless cast or they are not templates). 1) If structs are the same size: You can forcibly cast it so one will work with the other, however enums (or anything related that's static or not stored with the struct) doesn't transfer over and is lost. I've tried this in my experimental polymorphic struct; Where the methods differed slightly but data the structure is guaranteed to be identical. 2) Conversion/Accessing differences: You can include a flag specifying it's of a certain type or qualification, this can let them interact if they are basically the same thing with something minor under the hood different but that doesn't matter (or will get in the way); Although unqual (or related in std.traits) might be a better option for it, not sure myself. struct MyStruct(WEIGHTS) { enum isMyStruct = true; } void test(T1, T2)(T1 lhs, T2 rhs) if (hasMember!(T1, "isMyStruct") && hasMember!(T2, "isMyStruct")) {} 3) non-Template: As mentioned you can avoid templates & different enums and instead use variables as appropriate. I'm sure there's other ideas but I'm drawing a blank right now...enum FirstWeights : double { }enum SecondWeights : double { double foo = 0.3, double bar = 0.4 } so: auto s1 = MyStruct!FirstWeights ... auto s2 = MyStruct!SecondWeights ...
Mar 01 2013
On Friday, 1 March 2013 at 16:38:39 UTC, Era Scarecrow wrote:On Friday, 1 March 2013 at 14:32:12 UTC, Andrea Fontana wrote:Maybe if i have MyStruct!Weights1 arr[]; MyStruct!Weights2 arr2[]; instead of trying to merge them, and call: myfunc(singlebigarray); I should write a template function with a variadic number of params: myfunc(arr1, arr2, arr3 etc...); Or simply come back to basic ineritance or previous solution, was just a challenge to find a compile time way to pre-compute all consts factors...struct MyStruct(WEIGHTS) { string ... string ... alias WEIGHTS weights; }With templates there's a few different ways you can consider handling it; I'm not recommending any of them but. Keeping it simple, clean & easy to read is probably the best solution; Although most of these won't help with any algorithms that need them to be identical (unless cast or they are not templates). 1) If structs are the same size: You can forcibly cast it so one will work with the other, however enums (or anything related that's static or not stored with the struct) doesn't transfer over and is lost. I've tried this in my experimental polymorphic struct; Where the methods differed slightly but data the structure is guaranteed to be identical. 2) Conversion/Accessing differences: You can include a flag specifying it's of a certain type or qualification, this can let them interact if they are basically the same thing with something minor under the hood different but that doesn't matter (or will get in the way); Although unqual (or related in std.traits) might be a better option for it, not sure myself. struct MyStruct(WEIGHTS) { enum isMyStruct = true; } void test(T1, T2)(T1 lhs, T2 rhs) if (hasMember!(T1, "isMyStruct") && hasMember!(T2, "isMyStruct")) {} 3) non-Template: As mentioned you can avoid templates & different enums and instead use variables as appropriate. I'm sure there's other ideas but I'm drawing a blank right now...enum FirstWeights : double { }enum SecondWeights : double { double foo = 0.3, double bar = 0.4 } so: auto s1 = MyStruct!FirstWeights ... auto s2 = MyStruct!SecondWeights ...
Mar 01 2013