digitalmars.D - Strange Error using parameterized opAssign for a struct
- d coder (24/25) Jul 04 2011 Greetings All
- Robert Jacques (24/35) Jul 04 2011 Yes and No. DMD has trouble deducing the correct template parameters for...
Greetings All I have a Struct (see minimized code below) which is failing for a simple assignment. I am using DMD 2.053, and am getting an error:implicit.d(14): Error: cannot implicitly convert expression (foo1) of typeFoo!(4) to Foo!(NN) Am I doing something wrong, or have I hit a DMD bug? Kindly note that this happens only when I parameterize the struct using an Integral parameter, and works file when using string as parameter (as with struct Bar in the code). Regards - Puneet // File implicit.d struct Foo (size_t N) { void opAssign (size_t NN)(Foo!(NN) f) {/*do nothing*/} } struct Bar (string S) { void opAssign (string SS)(Bar!(SS) f) {/*do nothing*/} } void main() { Bar!"BAR1" bar1; Bar!"BAR2" bar2; bar2 = bar1; // this compiles fine Foo!4 foo1; Foo!4 foo2; foo2 = foo1; // compilation error }
Jul 04 2011
On Mon, 04 Jul 2011 05:58:45 -0400, d coder <dlang.coder gmail.com> wrote:Greetings All I have a Struct (see minimized code below) which is failing for a simple assignment. I am using DMD 2.053, and am getting an error:Yes and No. DMD has trouble deducing the correct template parameters for implicit function template instantiating when you make the template parameter the input to another template. The solution is to match a general type T and constrain it. (DMD can do these more complex matches inside an is expression, etc. So you can rewrite your code as: // File implicit.d struct Foo (size_t N) { void opAssign (T:Foo!NN,size_t NN)(T f) {/*do nothing*/} } struct Bar (string S) { void opAssign (string SS)(Bar!(SS) f) {/*do nothing*/} } void main() { Bar!"BAR1" bar1; Bar!"BAR2" bar2; bar2 = bar1; // this compiles fine Foo!4 foo1; Foo!4 foo2; foo2 = foo1; // Now compiles } Also, if you want to instantiate a Foo!NN, IIRC there's similar bug where the type becomes Foo!NN and not Foo!4. The solution is to use Foo!(NN+0) (or T) instead.implicit.d(14): Error: cannot implicitly convert expression (foo1) of type Foo!(4) to Foo!(NN)Am I doing something wrong, or have I hit a DMD bug? Kindly note that this happens only when I parameterize the struct using an Integral parameter, and works file when using string as parameter (as with struct Bar in the code). Regards - Puneet
Jul 04 2011
Thanks Robert Meanwhile, I also found that my code works it I change parameter type to int instead of size_t. Looks like DMD fails because of some issue with implicit conversions (or lack of it) between integral types. Anyway the solution you provided is more elegant and I will adopt that. Regards - Puneet
Jul 04 2011
Greetings Robert/All Robert suggested that I put my opAssign method as: void opAssign (T:Foo!NN,size_t NN)(T f) { } That works. But I want to find out if it is possible to write the opAssign template method with a conditional in the following form. This will help me optimize code better. Kindly suggest what would come in place of ....... below. void opAssign (T)(T f) if(is(T .......)) { } Regards - Puneet
Jul 04 2011
Robert suggested that I put my opAssign method as: void opAssign (T:Foo!NN,size_t NN)(T f) { } That works. But I want to find out if it is possible to write the opAssign template method with a conditional in the following form. This will help me optimize code better. Kindly suggest what would come in place of ....... below. void opAssign (T)(T f) if(is(T .......)) { }void opAssign (T)(T f) if(is(T L : Foo!(NN,MM), int NN, int MM)) { } I found that the above declaration compiles. But again it compiles with int as parameter type. Fails for size_t. Any other idea? Regards - Puneet
Jul 05 2011
Hello Robert As I try adding more code, I get into more and more issues with integral parameters. See the following code: Regards - Puneet // File implicit.d alias int R; // alias size_t R; struct Foo (R N) { version(v1) {void opAssign (R NN)(Foo!NN f) {/*do nothing*/}} version(v2) {void opAssign (T:Foo!NN, R NN)(T f) {/*do nothing*/}} property Foo!(I) range(R I)() {return Foo!(I)();} } void main() { Foo!4 foo1; Foo!7 foo2; foo2 = foo1; // compiles with both v2 and v1/(only when R is aliased to int) foo2 = foo1.range!4; // compiles with v1/int and v2/int -- does not compile with R alias to size_t foo2 = foo1.range!2; // compiles only with v1/int -- does not compile with v2 at all }
Jul 05 2011