Re: class template conflict
On 12/23/18 7:09 AM, Michelle Long wrote: class X { } class X(int N) : X { } Is there any real reason we can't do this? I think it has less to do with class names and more to do with symbol overloading. The only place I think templates are allowed to overload names with non-templates is functions, which actually was not always the case (you used to have to only have templates or non templates as function overloads). It is very nice to be able to treat X like the base and X!n as a derived class. The problem I see is: template foo(alias A) { ... } foo!X Did you mean class X or template X? For functions, this is OK, because it's one overload set. -Steve
Re: class template conflict
More simple is : do not use the same identifier ;) The whole point is to use the same identifier ;/
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 19:10:06 UTC, Alex wrote: On Sunday, 23 December 2018 at 18:53:15 UTC, Vijay Nayar wrote: You're right, it does compile. I'm a bit surprised. I wonder if this is a relatively recent improvement in the language, because last time I ran into this I had no such luck. But after seeing that your example did work, I figured one could try to get the best of both worlds by using a strongly-typed wrapper function in one's class. So far it seems to work: import std.traits; class A(KeyT, alias HashF) { // Strongly-typed wrapper around template value parameter 'HashF'. static size_t hash(in KeyT key) { return HashF(key); } static this() { static assert(isCallable!HashF, "Hash function is not callable!"); static assert(Parameters!(HashF).length == 1, "Hash function must take 1 argument."); static assert(is(Parameters!(HashF)[0] : const(KeyT)), "Hash parameter must be const."); static assert(is(typeof(HashF(KeyT.init)) : size_t), "Hash function must return size_t type."); } KeyT data; size_t getHash() const { return hash(data); } } void main() { auto a = new A!(int, (int a) => cast(size_t) a); a.data = 5; a.getHash(); } I'm not sure, whether you need the static this() part at all, as all of the asserts the compiler should do even when they are absent... by isCallable you restrict the HashF to not use IFTI by calling HashF(key) you ensure implicitely, that Parameters!(HashF).length == 1 by having hash(in KeyT key) defined with an "in" you ensured, that HashF does not mutate the argument and by defining size_t getHash() you ensured the return type of HashF... You are correct again! Playing around with using classes and functions returning the wrong type or not having a const argument, it seems that the compiler will assure that all the conditions needed by the wrapper function are satisfied and give a clear error. I don't know when this happened, but this definitely makes the language a lot easier to use for these circumstances, and all the std.traits stuff in "static this()" can be thrown out.
Re: Where do I learn to use GtkD
On Tuesday, 30 October 2018 at 04:22:21 UTC, helxi wrote: On Sunday, 13 March 2016 at 19:28:57 UTC, karabuta wrote: Gtk3 from python3 has got I nice book with examples that are not so advanced but enough to get you doing real work(from a beginner point of view). GtkD seem to have changed the API structure compared to python3 Gtk3 and the demo examples just "show-off" IMO :). The documentation is really^ not good :) Any help on where I can get better leaning materials(GtkD)? Repo, blogs post, etc please Sorry for the shameless self plug, and I know it's already too late. I have been working on porting some of the pygtk examples to GtkD and covered almost the half of it. For anyone who is reading this thread please check out the repo I mention bellow. For experienced users of GtkD, please leave your PRs and suggestions. https://gitlab.com/9898287/gtkdnotes So you know your posts weren't in vain, I've been struggling with one of the fundamentals of signals and buttons for the last three days and your notes got me out of the mire. Thanks, helxi.
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 18:53:15 UTC, Vijay Nayar wrote: You're right, it does compile. I'm a bit surprised. I wonder if this is a relatively recent improvement in the language, because last time I ran into this I had no such luck. But after seeing that your example did work, I figured one could try to get the best of both worlds by using a strongly-typed wrapper function in one's class. So far it seems to work: import std.traits; class A(KeyT, alias HashF) { // Strongly-typed wrapper around template value parameter 'HashF'. static size_t hash(in KeyT key) { return HashF(key); } static this() { static assert(isCallable!HashF, "Hash function is not callable!"); static assert(Parameters!(HashF).length == 1, "Hash function must take 1 argument."); static assert(is(Parameters!(HashF)[0] : const(KeyT)), "Hash parameter must be const."); static assert(is(typeof(HashF(KeyT.init)) : size_t), "Hash function must return size_t type."); } KeyT data; size_t getHash() const { return hash(data); } } void main() { auto a = new A!(int, (int a) => cast(size_t) a); a.data = 5; a.getHash(); } I'm not sure, whether you need the static this() part at all, as all of the asserts the compiler should do even when they are absent... by isCallable you restrict the HashF to not use IFTI by calling HashF(key) you ensure implicitely, that Parameters!(HashF).length == 1 by having hash(in KeyT key) defined with an "in" you ensured, that HashF does not mutate the argument and by defining size_t getHash() you ensured the return type of HashF...
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 18:31:24 UTC, Alex wrote: On Sunday, 23 December 2018 at 18:13:25 UTC, Vijay Nayar wrote: For example, if you have a const function in your container like "T find() const", and this function needs to use that comparator, then you're out of luck because the compiler doesn't know that the comparator function is const and will not modify the objects being compared. Last time I ran into this problem, my solution was simply to give up on const. But now I'm running into it again and trying to think through it again before giving up again. Hm... still not sure... ;) This would compile and run: ´´´ import std.experimental.all; size_t myHashFunction(int a) { return cast(size_t) a; } void main() { auto b = new B!(int, myHashFunction); b.arr = 42.iota.array; assert(b.find == 1); } class B(T, alias HashF) { T[] arr; T find() const { foreach(el; arr) { if(HashF(el)) { return el; } } assert(0); } } ´´´ You're right, it does compile. I'm a bit surprised. I wonder if this is a relatively recent improvement in the language, because last time I ran into this I had no such luck. But after seeing that your example did work, I figured one could try to get the best of both worlds by using a strongly-typed wrapper function in one's class. So far it seems to work: import std.traits; class A(KeyT, alias HashF) { // Strongly-typed wrapper around template value parameter 'HashF'. static size_t hash(in KeyT key) { return HashF(key); } static this() { static assert(isCallable!HashF, "Hash function is not callable!"); static assert(Parameters!(HashF).length == 1, "Hash function must take 1 argument."); static assert(is(Parameters!(HashF)[0] : const(KeyT)), "Hash parameter must be const."); static assert(is(typeof(HashF(KeyT.init)) : size_t), "Hash function must return size_t type."); } KeyT data; size_t getHash() const { return hash(data); } } void main() { auto a = new A!(int, (int a) => cast(size_t) a); a.data = 5; a.getHash(); }
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 18:13:25 UTC, Vijay Nayar wrote: I've been playing with the idea of specifying the constraints or using "static assert" in the constructor. They are good options, but there's a few cases where they fall a bit short. For example, imagine you have a container class that needs a comparator function to be able to compare the items in the container. While you can use std.traits to assure the right kind of function is passed in, that information does not make its way into the type system. For example, if you have a const function in your container like "T find() const", and this function needs to use that comparator, then you're out of luck because the compiler doesn't know that the comparator function is const and will not modify the objects being compared. Last time I ran into this problem, my solution was simply to give up on const. But now I'm running into it again and trying to think through it again before giving up again. Hm... still not sure... ;) This would compile and run: ´´´ import std.experimental.all; size_t myHashFunction(int a) { return cast(size_t) a; } void main() { auto b = new B!(int, myHashFunction); b.arr = 42.iota.array; assert(b.find == 1); } class B(T, alias HashF) { T[] arr; T find() const { foreach(el; arr) { if(HashF(el)) { return el; } } assert(0); } } ´´´
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 18:04:32 UTC, Alex wrote: On Sunday, 23 December 2018 at 17:13:49 UTC, Vijay Nayar wrote: I have a few cases where I would like to pass in a function as a value to a template, but I want to ensure that the function takes certain kinds of parameters, is a const function, or matches any other set of conditions. I assume you are looking for constraints... https://dlang.org/concepts.html Then, case B is the way to go, see https://run.dlang.io/is/jWU3tr Case D also looks promising. Not sure, how to formulate the specialization right now... There are a lot of traits you can use for the constraints. https://dlang.org/phobos/std_traits.html and https://dlang.org/spec/traits.html e.g., for constness there is getFunctionAttributes, which could be useful. I've been playing with the idea of specifying the constraints or using "static assert" in the constructor. They are good options, but there's a few cases where they fall a bit short. For example, imagine you have a container class that needs a comparator function to be able to compare the items in the container. While you can use std.traits to assure the right kind of function is passed in, that information does not make its way into the type system. For example, if you have a const function in your container like "T find() const", and this function needs to use that comparator, then you're out of luck because the compiler doesn't know that the comparator function is const and will not modify the objects being compared. Last time I ran into this problem, my solution was simply to give up on const. But now I'm running into it again and trying to think through it again before giving up again.
Re: Best Way to Pass Template Typed Alias Parameters for Functions?
On Sunday, 23 December 2018 at 17:13:49 UTC, Vijay Nayar wrote: I have a few cases where I would like to pass in a function as a value to a template, but I want to ensure that the function takes certain kinds of parameters, is a const function, or matches any other set of conditions. What is the best way to do this? Just to avoid any potential confusion, I've included a few examples below. I'm using explicit functions rather than lambdas just avoid any possibility of types being incorrectly inferred. size_t myHashFunction(int a) { return cast(size_t) a; } void main() { class A(KeyT, HashF) { } auto a = new A!(int, myHashFunction); // ^ onlineapp.d: Error: template instance `A!(int, myHashFunction)` // does not match template declaration `A(KeyT, HashF)` // Alias parameter: https://dlang.org/spec/template.html#aliasparameters class B(KeyT, alias HashF) { } auto b = new B!(int, myHashFunction); // ^ Works, but we cannot enforce the kind of function passed in. // Typed alias parameter: https://dlang.org/spec/template.html#typed_alias_op class C(KeyT, alias size_t function(KeyT) HashF) { } auto c = new C!(int, myHashFunction); // ^ onlineapp.d: Error: template instance `C!(int, myHashFunction)` // does not match template declaration `C(KeyT, alias size_t function(KeyT) HashF)` // Specialization: https://dlang.org/spec/template.html#alias_parameter_specialization class D(KeyT, alias HashF : size_t function(KeyT)) { } auto d = new D!(int, myHashFunction // ^ onlineapp.d: Error: template instance `D!(int, myHashFunction)` // does not match template declaration `D(KeyT, alias HashF : size_t function(KeyT))` } Looking at some of the code in std.algorithm, it seem that static asserts are sometimes used for this purpose. Does anyone have a solution to this problem of instantiating template classes whose parameters are functions? I have used std.function "unaryFun" before, but this has the problem of not being able to specify function attributes, like const. I assume you are looking for constraints... https://dlang.org/concepts.html Then, case B is the way to go, see https://run.dlang.io/is/jWU3tr Case D also looks promising. Not sure, how to formulate the specialization right now... There are a lot of traits you can use for the constraints. https://dlang.org/phobos/std_traits.html and https://dlang.org/spec/traits.html e.g., for constness there is getFunctionAttributes, which could be useful.
Best Way to Pass Template Typed Alias Parameters for Functions?
I have a few cases where I would like to pass in a function as a value to a template, but I want to ensure that the function takes certain kinds of parameters, is a const function, or matches any other set of conditions. What is the best way to do this? Just to avoid any potential confusion, I've included a few examples below. I'm using explicit functions rather than lambdas just avoid any possibility of types being incorrectly inferred. size_t myHashFunction(int a) { return cast(size_t) a; } void main() { class A(KeyT, HashF) { } auto a = new A!(int, myHashFunction); // ^ onlineapp.d: Error: template instance `A!(int, myHashFunction)` // does not match template declaration `A(KeyT, HashF)` // Alias parameter: https://dlang.org/spec/template.html#aliasparameters class B(KeyT, alias HashF) { } auto b = new B!(int, myHashFunction); // ^ Works, but we cannot enforce the kind of function passed in. // Typed alias parameter: https://dlang.org/spec/template.html#typed_alias_op class C(KeyT, alias size_t function(KeyT) HashF) { } auto c = new C!(int, myHashFunction); // ^ onlineapp.d: Error: template instance `C!(int, myHashFunction)` // does not match template declaration `C(KeyT, alias size_t function(KeyT) HashF)` // Specialization: https://dlang.org/spec/template.html#alias_parameter_specialization class D(KeyT, alias HashF : size_t function(KeyT)) { } auto d = new D!(int, myHashFunction // ^ onlineapp.d: Error: template instance `D!(int, myHashFunction)` // does not match template declaration `D(KeyT, alias HashF : size_t function(KeyT))` } Looking at some of the code in std.algorithm, it seem that static asserts are sometimes used for this purpose. Does anyone have a solution to this problem of instantiating template classes whose parameters are functions? I have used std.function "unaryFun" before, but this has the problem of not being able to specify function attributes, like const.
Re: class template conflict
On Sunday, 23 December 2018 at 12:09:31 UTC, Michelle Long wrote: class X { } class X(int N) : X { } Is there any real reason we can't do this? It is very nice to be able to treat X like the base and X!n as a derived class. Sure we can do class X(int N) : X!0 { static if(N == 0) { } } but this is very ugly, in my code I always have to use X!0 as the basis! I do not think there is any harm to allow this since the templated class always has to specify N. It is not like we can do class X(int N = 0) : X { static if(N == 0) { } } Actually we can, so... I don't see the point in not allowing the first case, they are logically equivalent. That static if is just ugly and it is defining the base class inside the derived class which seems unnatural. You have this option too: ``` template X(N...) if (N.length == 0 || N.length == 1 && is(typeof(N[0]) == int)) { static if (N.length == 0) class X {} else class X : X!() {} } auto base = new X!(); auto derived = new X!8; ``` More simple is : do not use the same identifier ;)
cas and interfaces
I recently played around with atomic operations. While doing so, I noticed a problem with the interaction of interfaces and cas. Consider the following program: ``` import core.atomic; import std.stdio; interface TestInterface { } class TestClass : TestInterface { } void main() { shared TestInterface testInterface = new shared TestClass; cas(, testInterface, new shared TestClass).writeln; writeln(typeid(testInterface)); } ``` (https://run.dlang.io/is/9P7PAb) This program compiles successfully and outputs ``` true Error: program killed by signal 11 ``` i.e. a segmentation fault happens. When replacing "interface" with "abstract class" (https://run.dlang.io/is/sFaO1k), everything works as expected and the program outputs ``` true onlineapp.TestClass ``` Is this actually a bug or a fundamental limitation of cas and interfaces? Did I do anything wrong?
class template conflict
class X { } class X(int N) : X { } Is there any real reason we can't do this? It is very nice to be able to treat X like the base and X!n as a derived class. Sure we can do class X(int N) : X!0 { static if(N == 0) { } } but this is very ugly, in my code I always have to use X!0 as the basis! I do not think there is any harm to allow this since the templated class always has to specify N. It is not like we can do class X(int N = 0) : X { static if(N == 0) { } } Actually we can, so... I don't see the point in not allowing the first case, they are logically equivalent. That static if is just ugly and it is defining the base class inside the derived class which seems unnatural.