www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template args to UDA's

reply Manu <turkeyman gmail.com> writes:
So I've run into an expression I need to be able to implement std.simd
properly for GDC/LDC.

Doesn't work:
   attribute("target", T) void func(string T)(...);

In this case, currently, the UDA can't receive the template arg that was
given to the function.

I require that attributes on templates be able to make use of the template
args, since the template arg given may affect the attribute in some
circumstances.
May 28 2013
next sibling parent reply "Diggory" <diggsey googlemail.com> writes:
On Tuesday, 28 May 2013 at 13:41:42 UTC, Manu wrote:
 So I've run into an expression I need to be able to implement 
 std.simd
 properly for GDC/LDC.

 Doesn't work:
    attribute("target", T) void func(string T)(...);

 In this case, currently, the UDA can't receive the template arg 
 that was
 given to the function.

 I require that attributes on templates be able to make use of 
 the template
 args, since the template arg given may affect the attribute in 
 some
 circumstances.

Can you not move the template outside the attribute like this?: template func(string T) { attribute("target", T) void func(...); }
May 28 2013
next sibling parent reply Manu <turkeyman gmail.com> writes:
On 29 May 2013 10:46, Diggory <diggsey googlemail.com> wrote:

 On Tuesday, 28 May 2013 at 13:41:42 UTC, Manu wrote:

 So I've run into an expression I need to be able to implement std.simd
 properly for GDC/LDC.

 Doesn't work:
    attribute("target", T) void func(string T)(...);

 In this case, currently, the UDA can't receive the template arg that was
 given to the function.

 I require that attributes on templates be able to make use of the template
 args, since the template arg given may affect the attribute in some
 circumstances.

Can you not move the template outside the attribute like this?: template func(string T) { attribute("target", T) void func(...); }

Yes, that's Kenji's initial suggestion, which I can use for now, but it feels like a workaround. It feels pretty lame to have to wrap select functions in an arbitrary outer scope, and it also has some subtle implications; how does auto-complete/intellisense see it? As a template, or as whatever it resolves to? The latter would imply some pretty powerful semantic analysis, and if there's static logic inside the template? The IDE basically won't work properly for any of these functions. Either way, the attribute certainly looks like it's part of the declaration, I think any reasoning programmer would assume that it is. It's only a DMD implementation detail that says otherwise, and it's not particularly intuitive to a programmer.
May 28 2013
next sibling parent "Diggory" <diggsey googlemail.com> writes:
 Yes, that's Kenji's initial suggestion, which I can use for

Ah, didn't see it because the forum keeps breaking threads up into little pieces...
May 28 2013
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 May 2013 21:08:42 -0400, Manu <turkeyman gmail.com> wrote:

 On 29 May 2013 10:46, Diggory <diggsey googlemail.com> wrote:

 Can you not move the template outside the attribute like this?:

 template func(string T) {
      attribute("target", T) void func(...);
 }

Yes, that's Kenji's initial suggestion, which I can use for now, but it feels like a workaround. It feels pretty lame to have to wrap select functions in an arbitrary outer scope, and it also has some subtle implications; how does auto-complete/intellisense see it? As a template, or as whatever it resolves to?

It's not a workaround, nor arbitrary. In fact: func(string T)(...) is EXACTLY equivalent to: template func(string T) { func(...) } The compiler implicitly converts the former to the latter. In fact, the formal name of func!"foo"() is func!"foo".func() in both cases.
 The latter would imply some pretty powerful semantic analysis, and if
 there's static logic inside the template? The IDE basically won't work
 properly for any of these functions.

Any conditional compilation breaks IFTI. This is required, since the "magic" of IFTI means it must partially instantiate the template to see whether the function parameters match. It could very easily get stuck in the weeds through some arbitrary conditional compilation.
 Either way, the attribute certainly looks like it's part of the
 declaration, I think any reasoning programmer would assume that it is.  
 It's
 only a DMD implementation detail that says otherwise, and it's not
 particularly intuitive to a programmer.

On this, I agree. But it is important to remember that a function template is first a template and then a function. When you apply attributes to it, you are applying it to the outer-most piece -- the template. And IATI (implicit attribute template instantiation) isn't available yet :) I think it's awesome that IFTI handles this messy detail, and it would be nice if uda's were part of that messy detail. -Steve
May 28 2013
prev sibling next sibling parent Kenji Hara <k.hara.pg gmail.com> writes:
2013/5/29 Manu <turkeyman gmail.com>

 Either way, the attribute certainly looks like it's part of the
 declaration, I think any reasoning programmer would assume that it is. It's
 only a DMD implementation detail that says otherwise, and it's not
 particularly intuitive to a programmer.

It's not a dmd implementation detail. It is part of current D language design. dmd works as well. No bug there, so this is definitely an enhancement. But I can agree that is a little not good from human sense. I know a related issue. struct S { immutable int foo() {} // immutable is prefix attribute (==storage class) } In above, `immutable` would be applied to the declaration `foo`, not its return type `int`. But, changing semantics would break much existing code. Your enhancement belongs same area. We need to get agreement of D programmers first. Kenji Hara
May 28 2013
prev sibling parent Manu <turkeyman gmail.com> writes:
On 29 May 2013 11:18, Kenji Hara <k.hara.pg gmail.com> wrote:

 2013/5/29 Manu <turkeyman gmail.com>

 Either way, the attribute certainly looks like it's part of the
 declaration, I think any reasoning programmer would assume that it is. It's
 only a DMD implementation detail that says otherwise, and it's not
 particularly intuitive to a programmer.

It's not a dmd implementation detail. It is part of current D language design. dmd works as well. No bug there, so this is definitely an enhancement. But I can agree that is a little not good from human sense. I know a related issue. struct S { immutable int foo() {} // immutable is prefix attribute (==storage class) } In above, `immutable` would be applied to the declaration `foo`, not its return type `int`. But, changing semantics would break much existing code. Your enhancement belongs same area. We need to get agreement of D programmers first.

Yeah, that's a good point, I've never liked that ambiguity. I always write: immutable(int) foo() {} Otherwise I never really know what to expect.
May 28 2013
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, May 29, 2013 11:28:06 Manu wrote:
 On 29 May 2013 11:18, Kenji Hara <k.hara.pg gmail.com> wrote:
 But I can agree that is a little not good from human sense. I know a
 related issue.
 
 struct S {
 
 immutable int foo() {} // immutable is prefix attribute (==storage
 
 class)
 }
 
 In above, `immutable` would be applied to the declaration `foo`, not its
 return type `int`.
 
 But, changing semantics would break much existing code. Your enhancement
 belongs same area. We need to get agreement of D programmers first.

Yeah, that's a good point, I've never liked that ambiguity. I always write: immutable(int) foo() {} Otherwise I never really know what to expect.

Well, it's not actually ambiguous at all. It's just undesirable. If the const, immutable, or inout uses parens around the return type, then it's the return type which is const, immutable, or inout. In all other cases, it's the function (and thus the this pointer). So, it's completely clear if you know the rules, but the rules suck. Unfortunately, if function attributes which could affect the return type could only go on the right (as is the case with C++), then those function attributes would be inconsistent with the others, and Walter doesn't like that. Enforcing that all function attributes always go on the right would fix that, but I expect that that's too different from C++, Java, etc. for that to have ever been acceptable, and at this point, it would break too much code for Walter to agree to change it. - Jonathan M Davis
May 28 2013