digitalmars.D.learn - How do I initialize a templated constructor?
- rempas (27/27) Aug 07 2022 In the following struct (as an example, not real code):
- bauss (52/79) Aug 07 2022 ```
- rempas (6/57) Aug 08 2022 Thank you for all the great info! Unfortunately, while there is
- bauss (8/13) Aug 08 2022 Yeah I think the only template argument you can have for
- rempas (4/12) Aug 08 2022 Oh, trust me! I didn't designed my program wrong in my case.
- Dom Disc (12/25) Aug 08 2022 But if you only want to know the type of the parameter, you can
- WebFreak001 (20/47) Aug 08 2022 I would move the constructor out of the struct into a helper
- =?UTF-8?Q?Ali_=c3=87ehreli?= (18/23) Aug 08 2022 The following method uses a convenience function but it's not really nee...
- Steven Schveighoffer (10/44) Aug 08 2022 You cannot explicitly specify template parameters for constructors.
- Steven Schveighoffer (23/69) Aug 08 2022 Just thought of another possibility:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (18/18) Aug 08 2022 Here is another one that uses nested templates:
- rempas (3/3) Aug 08 2022 Thank you all for the info! I'll try to find another way to do it
In the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that. Is there a way you guys know? I have tried the following: ``` void main() { // Doesn't work auto val = TestArray!(10, "int")(60); // Doesn't work either auto val = TestArray!(10).TestArray!("int")(60); // Neither this works.... auto val = TestArray!(10).this!("int")(60); } ``` As with every question I make, the solution must be "betterC" compatible so I can use it. Thanks a lot!
Aug 07 2022
On Monday, 8 August 2022 at 05:38:31 UTC, rempas wrote:In the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that. Is there a way you guys know? I have tried the following: ``` void main() { // Doesn't work auto val = TestArray!(10, "int")(60); // Doesn't work either auto val = TestArray!(10).TestArray!("int")(60); // Neither this works.... auto val = TestArray!(10).this!("int")(60); } ``` As with every question I make, the solution must be "betterC" compatible so I can use it. Thanks a lot!``` this(string type)(ulong number) { ``` You cannot do this. Instead your type should look like this: First let's change it up a little bit. ``` struct TestArray(ulong element_n, string type) { int[element_n] elements; this(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` Now the above will still not work because you do `typeof(type)` which will always yield string because type is as string and also the typeof() is not needed in this case and will actually yield an error. If it must be a string then you can do it like this: ``` struct TestArray(ulong element_n, string type) { int[element_n] elements; this(ulong number) { mixin("alias T = " ~ type ~ ";"); pragma(msg, "The type is: " ~ T.stringof); } } ``` However the ideal implementation is probably this: ``` struct TestArray(ulong element_n, T) { int[element_n] elements; this(ulong number) { pragma(msg, "The type is: " ~ T.stringof); } } ``` To instantiate it you simply do: ``` TestArray!(10, "int") val = TestArray!(10, "int")(100); ``` Or ``` TestArray!(10, int) val = TestArray!(10, int)(100); ``` I will recommend an alias to make it easier: ``` alias IntTestArray = TestArray!(10, int); ... IntTestArray val = IntTestArray(100); ```
Aug 07 2022
On Monday, 8 August 2022 at 06:58:42 UTC, bauss wrote:``` this(string type)(ulong number) { ``` You cannot do this. Instead your type should look like this: First let's change it up a little bit. ``` struct TestArray(ulong element_n, string type) { int[element_n] elements; this(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` Now the above will still not work because you do `typeof(type)` which will always yield string because type is as string and also the typeof() is not needed in this case and will actually yield an error. If it must be a string then you can do it like this: ``` struct TestArray(ulong element_n, string type) { int[element_n] elements; this(ulong number) { mixin("alias T = " ~ type ~ ";"); pragma(msg, "The type is: " ~ T.stringof); } } ``` However the ideal implementation is probably this: ``` struct TestArray(ulong element_n, T) { int[element_n] elements; this(ulong number) { pragma(msg, "The type is: " ~ T.stringof); } } ``` To instantiate it you simply do: ``` TestArray!(10, "int") val = TestArray!(10, "int")(100); ``` Or ``` TestArray!(10, int) val = TestArray!(10, int)(100); ``` I will recommend an alias to make it easier: ``` alias IntTestArray = TestArray!(10, int); ... IntTestArray val = IntTestArray(100); ```Thank you for all the great info! Unfortunately, while there is no problem in this example, this will not do for my real code as I need to have the argument in the constructor. Alternative, I have to change the design of the program completely....
Aug 08 2022
On Monday, 8 August 2022 at 07:37:16 UTC, rempas wrote:Thank you for all the great info! Unfortunately, while there is no problem in this example, this will not do for my real code as I need to have the argument in the constructor. Alternative, I have to change the design of the program completely....Yeah I think the only template argument you can have for constructors are `this` which will refer to things like the class that inherited the current class etc. not sure what else, but you can't really pass anything to it yourself unfortunately. But I think if you end up with something where you need different constructors with different type arguments then you're probably designing your program in a "wrong" way to begin with.
Aug 08 2022
On Monday, 8 August 2022 at 08:27:49 UTC, bauss wrote:Yeah I think the only template argument you can have for constructors are `this` which will refer to things like the class that inherited the current class etc. not sure what else, but you can't really pass anything to it yourself unfortunately.It's fine, thanks for trying in any case!But I think if you end up with something where you need different constructors with different type arguments then you're probably designing your program in a "wrong" way to begin with.Oh, trust me! I didn't designed my program wrong in my case. At least not the way I see it!
Aug 08 2022
On Monday, 8 August 2022 at 06:58:42 UTC, bauss wrote:On Monday, 8 August 2022 at 05:38:31 UTC, rempas wrote:But if you only want to know the type of the parameter, you can do this: ```D struct TestArray(ulong element_n) { int[element_n] elements; this(type)(type number) { pragma(msg, "The type is: " ~ type.stringof); } } ```In the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ```You cannot do this.
Aug 08 2022
And then you can instantiate it with ```D auto val = TestArray!10(ubyte(60)); // if you want type to be ubyte ```
Aug 08 2022
On Monday, 8 August 2022 at 11:03:21 UTC, Dom Disc wrote:But if you only want to know the type of the parameter, you can do this: ```D struct TestArray(ulong element_n) { int[element_n] elements; this(type)(type number) { pragma(msg, "The type is: " ~ type.stringof); } } ```Unfortunately this will not do as well....
Aug 08 2022
On Monday, 8 August 2022 at 12:26:50 UTC, rempas wrote:On Monday, 8 August 2022 at 11:03:21 UTC, Dom Disc wrote:You should first describe what you want to do clearly.
Aug 08 2022
On Monday, 8 August 2022 at 05:38:31 UTC, rempas wrote:In the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that. Is there a way you guys know? I have tried the following: ``` void main() { // Doesn't work auto val = TestArray!(10, "int")(60); // Doesn't work either auto val = TestArray!(10).TestArray!("int")(60); // Neither this works.... auto val = TestArray!(10).this!("int")(60); } ``` As with every question I make, the solution must be "betterC" compatible so I can use it. Thanks a lot!I would move the constructor out of the struct into a helper function, either global or as a static member: ```d TestArray!n testArray(ulong n, string type)(ulong number) { TestArray!n ret; pragma(msg, "The type is: " ~ typeof(type).stringof); ret.something = something; // do your constructor logic here return ret; } ``` which you can then use: ```d auto t = testArray!(10, "int")(60); ``` As the template parameter being part of the constructor would only change the constructor (and can't change anything like types outside the ctor) it doesn't have any limitations and if you define it in the same module as the struct you can also access the private members.
Aug 08 2022
On 8/7/22 22:38, rempas wrote:I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that.The following method uses a convenience function but it's not really needed: import std.stdio; struct TestArray(ulong element_n, string type) { int[element_n] elements; mixin(type) member; pragma(msg, "The type is: ", typeof(member)); this(ulong number) { writeln("Constructing with ", number); } } auto makeTestArray(ulong element_n, string type)(ulong number) { return TestArray!(element_n, type)(number); } void main() { auto ta = makeTestArray!(10, "int")(60); } Ali
Aug 08 2022
On 8/8/22 1:38 AM, rempas wrote:In the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that. Is there a way you guys know? I have tried the following: ``` void main() { // Doesn't work auto val = TestArray!(10, "int")(60); // Doesn't work either auto val = TestArray!(10).TestArray!("int")(60); // Neither this works.... auto val = TestArray!(10).this!("int")(60); } ``` As with every question I make, the solution must be "betterC" compatible so I can use it. Thanks a lot!You cannot explicitly specify template parameters for constructors. The only true solution is to use a factory function: ```d TestArray!T testarray(string s, T)(T val) { ... // code that depends on s here return TestArray!T(...) // call ctor here. } ``` -Steve
Aug 08 2022
On 8/8/22 9:36 AM, Steven Schveighoffer wrote:On 8/8/22 1:38 AM, rempas wrote:Just thought of another possibility: ```d struct StringAnnotated(string s, T) { T val; } StringAnnotated!(s, T) annotate(string s, T)(T val) { return StringAnnotated!(s, T)(val); } struct TestArray(ulong element_n) { ... this(T)(T val) if (isInstanceOf!(StringAnnotated, T)) { ... } } // use like TestArray!10(60.annotate!"int"); ``` -SteveIn the following struct (as an example, not real code): ``` struct TestArray(ulong element_n) { int[element_n] elements; this(string type)(ulong number) { pragma(msg, "The type is: " ~ typeof(type).stringof); } } ``` I want to create it and be able to successfully initialize the template parameters of the constructor but until now, I wasn't able to find a way to successfully do that. Is there a way you guys know? I have tried the following: ``` void main() { // Doesn't work auto val = TestArray!(10, "int")(60); // Doesn't work either auto val = TestArray!(10).TestArray!("int")(60); // Neither this works.... auto val = TestArray!(10).this!("int")(60); } ``` As with every question I make, the solution must be "betterC" compatible so I can use it. Thanks a lot!You cannot explicitly specify template parameters for constructors. The only true solution is to use a factory function: ```d TestArray!T testarray(string s, T)(T val) { ... // code that depends on s here return TestArray!T(...) // call ctor here. } ```
Aug 08 2022
Here is another one that uses nested templates: import std.stdio; template TestArray(ulong element_n) { struct TestArrayImpl(Type) { int[element_n] elements; this(ulong number) { pragma(msg, "The type is: ", Type); writeln("Constructing with ", number); } } auto makeFor(string s)(ulong number) { return TestArrayImpl!(mixin(s))(number); } } void main() { auto ta = TestArray!10.makeFor!"int"(60); } Ali
Aug 08 2022
Thank you all for the info! I'll try to find another way to do it as it is not possible to match the exact behavior I want! Have a great day everyone!
Aug 08 2022