www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why isn't intended class constructor called?

reply Zak <zjost85 gmail.com> writes:
I have defined a class that's meant to represent a data series, 
which has an index and a set of values.  Sometimes the user wants 
to specify a particular index of custom type, other times they 
don't care and we want to default to an array of contiguous "int" 
starting from 0.

I have attempted to create a class where the index type is a 
parameter, but defaults to int.  I also tried to create two 
constructors:  one for if the index values are not specified (in 
which the constructor makes the array of ints); and one where the 
user passes in a literal of values that match the specified type.

However, it seems that only the first constructor is getting 
called, even though I am passing in two parameters instead of 
one.  Why isn't the call matching the second constructor and 
behaving as intended?


  import std.stdio;

  class MyClass(T, U = int) {

     T[] values;
     U[] index;

     this(T[] values) {
         this.values = values;
         // Default index of contiguous ints
         for (int i; i < values.length; i++) {
             index ~= i;
         }
     }

     this(T[] values, U[] index) {
         this.values = values;
         this.index = index;
     }
}

void main() {
     auto myc1 = new MyClass!(int)([1,2,-3]);

     auto myc2 = new MyClass!(int, string)([1,2,-3], ["a", "b", 
"c"]); // Error: cannot append type int to type string[]

}
Jan 28
parent reply Alex <sascha.orlov gmail.com> writes:
On Monday, 28 January 2019 at 18:34:44 UTC, Zak wrote:
 I have defined a class that's meant to represent a data series, 
 which has an index and a set of values.  Sometimes the user 
 wants to specify a particular index of custom type, other times 
 they don't care and we want to default to an array of 
 contiguous "int" starting from 0.

 I have attempted to create a class where the index type is a 
 parameter, but defaults to int.  I also tried to create two 
 constructors:  one for if the index values are not specified 
 (in which the constructor makes the array of ints); and one 
 where the user passes in a literal of values that match the 
 specified type.

 However, it seems that only the first constructor is getting 
 called, even though I am passing in two parameters instead of 
 one.  Why isn't the call matching the second constructor and 
 behaving as intended?


  import std.stdio;

  class MyClass(T, U = int) {

     T[] values;
     U[] index;

     this(T[] values) {
         this.values = values;
         // Default index of contiguous ints
         for (int i; i < values.length; i++) {
             index ~= i;
         }
     }

     this(T[] values, U[] index) {
         this.values = values;
         this.index = index;
     }
 }

 void main() {
     auto myc1 = new MyClass!(int)([1,2,-3]);

     auto myc2 = new MyClass!(int, string)([1,2,-3], ["a", "b", 
 "c"]); // Error: cannot append type int to type string[]

 }
As the error states: you are trying to append an int to a string array in the single parameter constructor. This would work: ´´´ import std.stdio; class MyClass(T, U = int) { T[] values; U[] index; this(T[] values) { this.values = values; // Default index of contiguous ints static if(is(U == int)) { for (int i; i < values.length; i++) { index ~= i; } } } this(T[] values, U[] index) { this.values = values; this.index = index; } } void main() { auto myc1 = new MyClass!(int)([1,2,-3]); auto myc2 = new MyClass!(int, string)([1,2,-3], ["a", "b", "c"]); // Error: cannot append type int to type string[] } ´´´ If design matters, I would even to expand the static if above the constructor. So, the single parameter constructor would exist iff is(U == int) ´´´ static if(is(U == int)) { this(T[] values) { this.values = values; // Default index of contiguous ints for (int i; i < values.length; i++) { index ~= i; } } } ´´´
Jan 28
parent reply Zak <zjost85 gmail.com> writes:
On Monday, 28 January 2019 at 18:50:18 UTC, Alex wrote:
 On Monday, 28 January 2019 at 18:34:44 UTC, Zak wrote:
 [...]
As the error states: you are trying to append an int to a string array in the single parameter constructor. [...]
Thanks for the response, Alex! But it's not clear to me why the first constructor is called at all. Since I called with two parameters, shouldn't it invoke the second constructor?
Jan 28
parent reply Zak <zjost85 gmail.com> writes:
On Monday, 28 January 2019 at 19:15:04 UTC, Zak wrote:
 On Monday, 28 January 2019 at 18:50:18 UTC, Alex wrote:
 On Monday, 28 January 2019 at 18:34:44 UTC, Zak wrote:
 [...]
As the error states: you are trying to append an int to a string array in the single parameter constructor. [...]
Thanks for the response, Alex! But it's not clear to me why the first constructor is called at all. Since I called with two parameters, shouldn't it invoke the second constructor?
I think I just realized the answer: this section of code is not called, it just fails compilation since it's not known that runtime doesn't do something like: auto myc = new MyClass!(int, string)([1,2,-3]); which "would" invoke this code block with type string.
Jan 28
parent Alex <sascha.orlov gmail.com> writes:
On Monday, 28 January 2019 at 19:24:21 UTC, Zak wrote:
 On Monday, 28 January 2019 at 19:15:04 UTC, Zak wrote:
 On Monday, 28 January 2019 at 18:50:18 UTC, Alex wrote:
 On Monday, 28 January 2019 at 18:34:44 UTC, Zak wrote:
 [...]
As the error states: you are trying to append an int to a string array in the single parameter constructor. [...]
Thanks for the response, Alex! But it's not clear to me why the first constructor is called at all. Since I called with two parameters, shouldn't it invoke the second constructor?
I think I just realized the answer: this section of code is not called, it just fails compilation since it's not known that runtime doesn't do something like: auto myc = new MyClass!(int, string)([1,2,-3]); which "would" invoke this code block with type string.
Yes. :)
Jan 28