digitalmars.D.learn - hasUDA with this
- jmh530 (31/31) Jul 19 2018 I wanted to create a struct with a member function whose behavior
- Timoses (38/70) Jul 19 2018 I haven't worked with UDAs myself yet, but I believe that when
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (24/29) Jul 20 2018 UDAs apply to symbols. When you pass something to a function, the
- jmh530 (22/45) Jul 20 2018 That the UDAs don't copy with the values potentially throws my
- jmh530 (18/70) Jul 20 2018 Hmm, on that part about the attributes copying their values, I
- Timoses (4/21) Jul 20 2018 It works in module scope
- jmh530 (4/8) Jul 25 2018 This was reported in 2013. IMO, it should be mentioned in the
- Timoses (14/25) Jul 26 2018 I don't think that bug report relates to the initial question
- jmh530 (7/23) Jul 26 2018 True. But I was thinking about making a block that applies the
- =?UTF-8?Q?Ali_=c3=87ehreli?= (15/34) Jul 26 2018 It doesn't but the scope itself is legal in a nested scope; so, 'const'
- jmh530 (5/23) Jul 30 2018 We seem to be getting caught in scopes, when const: fails just as
I wanted to create a struct with a member function whose behavior was different depending on whether the struct instance had a particular UDA. However, it seems like hasUDA doesn't seem to produce the result I would have expected here. I tried using getAttributes, but that didn't work either. Am I missing something, or should I submit an enhancement request? import std.traits : hasUDA; enum test; struct Foo { int x; bool checkUDA() { static if (hasUDA!(this, test)) { return true; } else { return false; } } } void main() { import std.stdio : writeln; test Foo foo = Foo(1); static assert(hasUDA!(foo, test)); writeln(foo.checkUDA()); //prints false, expected true }
Jul 19 2018
On Thursday, 19 July 2018 at 19:18:43 UTC, jmh530 wrote:I wanted to create a struct with a member function whose behavior was different depending on whether the struct instance had a particular UDA. However, it seems like hasUDA doesn't seem to produce the result I would have expected here. I tried using getAttributes, but that didn't work either. Am I missing something, or should I submit an enhancement request? import std.traits : hasUDA; enum test; struct Foo { int x; bool checkUDA() { static if (hasUDA!(this, test)) { return true; } else { return false; } } } void main() { import std.stdio : writeln; test Foo foo = Foo(1); static assert(hasUDA!(foo, test)); writeln(foo.checkUDA()); //prints false, expected true }I haven't worked with UDAs myself yet, but I believe that when you apply something like test Foo foo; then you apply the UDA to `foo` and not to `Foo`. See below: enum test; struct Foo {} bool checkUDA(alias f)() { static if (hasUDA!(f, test)) { return true; } else { return false; } } void main() { test Foo foo; // same as `hasUDA!(foo, test)` assert(checkUDA!foo); //prints true } Now I'm really not sure how UDAs are best utilized, so above example might not be how it should be done.. However, you could make a templated version of checkUDA depending on what calls it. E.g. bool checkUDA(T, alias f)(T t) { // ... } although this leads to awkward calls like foo.checkUDA!foo which doesn't seem right either. Perhaps wait for somebody more knowledgeable to answer your question : D.
Jul 19 2018
On Thursday, 19 July 2018 at 19:18:43 UTC, jmh530 wrote:However, it seems like hasUDA doesn't seem to produce the result I would have expected here. I tried using getAttributes, but that didn't work either. Am I missing something, or should I submit an enhancement request?UDAs apply to symbols. When you pass something to a function, the symbol does not go with the value, and thus that UDA goes away. It's similar to assigning to a different variable: import std.traits : hasUDA; ("foo") Foo foo1; Foo foo2 = foo1; assert(!hasUDA!(foo2, "foo")); Since UDAs are compile-time constructs, they really can't follow values around in that way. Consider: void main(string[] args) { ("foo") Foo foo1; ("bar") Foo foo2; Foo foo3 = (args.length % 2) ? foo1 : foo2; assert(hasUDA!(foo3, "foo")); // Would you expect this to pass or fail? } Timoses first checkUDA function is exactly what I would suggest you use. -- Simen
Jul 20 2018
On Friday, 20 July 2018 at 07:25:23 UTC, Simen Kjærås wrote:UDAs apply to symbols. When you pass something to a function, the symbol does not go with the value, and thus that UDA goes away. It's similar to assigning to a different variable: import std.traits : hasUDA; ("foo") Foo foo1; Foo foo2 = foo1; assert(!hasUDA!(foo2, "foo")); Since UDAs are compile-time constructs, they really can't follow values around in that way. Consider: void main(string[] args) { ("foo") Foo foo1; ("bar") Foo foo2; Foo foo3 = (args.length % 2) ? foo1 : foo2; assert(hasUDA!(foo3, "foo")); // Would you expect this to pass or fail? } Timoses first checkUDA function is exactly what I would suggest you use. -- SimenThat the UDAs don't copy with the values potentially throws my idea into the crapper... Anyway, what I really wanted to do is change behavior of the struct, at compile-time, based on a UDA. For instance, what I really want is more like: struct Foo { static if (hasUDA!(this, DisableCasting)) { disable T opCast(T) { } } } So that if the instance has the particular UDA, then some kind of error would be thrown at compile-time that opCast was disabled. I don't really need anything at run-time. Obviously, I could do this as a template with a compile-time switch. I just wanted to see if it was possible with a UDA because then I could apply it to many different structs by just adding a template mixin of the above. I wouldn't need to make them different types. All functions that currently use them would work, unless there is a cast, in which case you know that at compile-time.
Jul 20 2018
On Friday, 20 July 2018 at 14:11:23 UTC, jmh530 wrote:On Friday, 20 July 2018 at 07:25:23 UTC, Simen Kjærås wrote:Hmm, on that part about the attributes copying their values, I suppose it would be sufficient if I could apply the attributes to a group of declarations. However, it didn't seem to work properly for me with UDAs, and I noticed that even some of the examples in the spec don't compile. Below is taken from section 8.5 and doesn't compile with DMD 2.081.1. (here's a version on run.dlang.org: https://run.dlang.io/is/pKHoBA) void main() { const int foo = 7; static assert(is(typeof(foo) == const(int))); const { double bar = foo + 6; } static assert(is(typeof(bar) == const(double))); }UDAs apply to symbols. When you pass something to a function, the symbol does not go with the value, and thus that UDA goes away. It's similar to assigning to a different variable: import std.traits : hasUDA; ("foo") Foo foo1; Foo foo2 = foo1; assert(!hasUDA!(foo2, "foo")); Since UDAs are compile-time constructs, they really can't follow values around in that way. Consider: void main(string[] args) { ("foo") Foo foo1; ("bar") Foo foo2; Foo foo3 = (args.length % 2) ? foo1 : foo2; assert(hasUDA!(foo3, "foo")); // Would you expect this to pass or fail? } Timoses first checkUDA function is exactly what I would suggest you use. -- SimenThat the UDAs don't copy with the values potentially throws my idea into the crapper... Anyway, what I really wanted to do is change behavior of the struct, at compile-time, based on a UDA. For instance, what I really want is more like: struct Foo { static if (hasUDA!(this, DisableCasting)) { disable T opCast(T) { } } } So that if the instance has the particular UDA, then some kind of error would be thrown at compile-time that opCast was disabled. I don't really need anything at run-time. Obviously, I could do this as a template with a compile-time switch. I just wanted to see if it was possible with a UDA because then I could apply it to many different structs by just adding a template mixin of the above. I wouldn't need to make them different types. All functions that currently use them would work, unless there is a cast, in which case you know that at compile-time.
Jul 20 2018
On Friday, 20 July 2018 at 16:53:12 UTC, jmh530 wrote:Hmm, on that part about the attributes copying their values, I suppose it would be sufficient if I could apply the attributes to a group of declarations. However, it didn't seem to work properly for me with UDAs, and I noticed that even some of the examples in the spec don't compile. Below is taken from section 8.5 and doesn't compile with DMD 2.081.1. (here's a version on run.dlang.org: https://run.dlang.io/is/pKHoBA) void main() { const int foo = 7; static assert(is(typeof(foo) == const(int))); const { double bar = foo + 6; } static assert(is(typeof(bar) == const(double))); }It works in module scope https://run.dlang.io/is/OQKYag I don't know why though...
Jul 20 2018
On Friday, 20 July 2018 at 18:24:11 UTC, Timoses wrote:[snip] It works in module scope https://run.dlang.io/is/OQKYag I don't know why though...This was reported in 2013. IMO, it should be mentioned in the spec if they don't plan on changing it. https://issues.dlang.org/show_bug.cgi?id=11064
Jul 25 2018
On Wednesday, 25 July 2018 at 21:17:38 UTC, jmh530 wrote:On Friday, 20 July 2018 at 18:24:11 UTC, Timoses wrote:I don't think that bug report relates to the initial question (UDA not applying to run-time instance). Regarding this example void fun() { /*const*/ { double bar; } static assert(!is (typeof(bar))); } it would kind of violate that `bar` is declared within its own scoped block if the static assert failed just because `const` was applied to the block.[snip] It works in module scope https://run.dlang.io/is/OQKYag I don't know why though...This was reported in 2013. IMO, it should be mentioned in the spec if they don't plan on changing it. https://issues.dlang.org/show_bug.cgi?id=11064
Jul 26 2018
On Thursday, 26 July 2018 at 08:08:17 UTC, Timoses wrote:On Wednesday, 25 July 2018 at 21:17:38 UTC, jmh530 wrote:True. But I was thinking about making a block that applies the UDA to everything within the block as a way to avoid the problem of copying the UDA to another variable.On Friday, 20 July 2018 at 18:24:11 UTC, Timoses wrote:(snip) I don't think that bug report relates to the initial question (UDA not applying to run-time instance).Regarding this example void fun() { /*const*/ { double bar; } static assert(!is (typeof(bar))); } it would kind of violate that `bar` is declared within its own scoped block if the static assert failed just because `const` was applied to the block.I don’t think the const block introduces a new scope. It works at the global level just fine. Public/private/etc are also a relevant example.
Jul 26 2018
On 07/26/2018 09:24 AM, jmh530 wrote:On Thursday, 26 July 2018 at 08:08:17 UTC, Timoses wrote:On Wednesday, 25 July 2018 at 21:17:38 UTC, jmh530 wrote:It doesn't but the scope itself is legal in a nested scope; so, 'const' should not remove the scope either.Regarding this example void fun() { /*const*/ { double bar; } static assert(!is (typeof(bar))); } it would kind of violate that `bar` is declared within its own scoped block if the static assert failed just because `const` was applied to the block.I don’t think the const block introduces a new scope.It works at the global level just fine.It must be because one cannot introduce a nested scope at the global scope: // illegal { double bar; } void main() { // legal { double bar; } } Ali
Jul 26 2018
On Thursday, 26 July 2018 at 16:52:31 UTC, Ali Çehreli wrote:[snip] It doesn't but the scope itself is legal in a nested scope; so, 'const' should not remove the scope either.We seem to be getting caught in scopes, when const: fails just as much as const {} does. The spec suggests that both of those work for all attributes including UDAs, when it only works on a limited subset outside of global scope.It works at the global level just fine.It must be because one cannot introduce a nested scope at the global scope: // illegal { double bar; } void main() { // legal { double bar; } } Ali
Jul 30 2018