Jump to page: 1 2 3
Thread overview
Getting the overload set of a template
Apr 17, 2018
Arafel
Apr 19, 2018
Simen Kjærås
Apr 19, 2018
Alex
Apr 19, 2018
Arafel
Apr 19, 2018
Simen Kjærås
Apr 21, 2018
Alex
Apr 21, 2018
Simen Kjærås
Apr 21, 2018
Alex
Apr 22, 2018
Simen Kjærås
Apr 22, 2018
Alex
Apr 23, 2018
Simen Kjærås
Apr 23, 2018
Alex
Apr 23, 2018
Simen Kjærås
Apr 23, 2018
Alex
Apr 23, 2018
Simen Kjærås
Apr 23, 2018
Alex
Apr 23, 2018
Simen Kjærås
Apr 23, 2018
Alex
Apr 23, 2018
Simen Kjærås
Apr 23, 2018
Alex
Apr 23, 2018
Arafel
Apr 23, 2018
Alex
Apr 23, 2018
Arafel
Apr 23, 2018
Alex
Apr 19, 2018
Simen Kjærås
April 17, 2018
Hi!

Is there any way to get the full set of templates that are "overloaded" (in my case, based on constraints)?

Basically, I'd like to make something like https://run.dlang.io/is/z2LeAj return both versions of the template (and then retrieve their UDAs)...

If it's not possible, I can still work around it, but I find it a bit frustrating that you can only access the first version of a template.

Thanks!

Arafel
April 19, 2018
On Tuesday, 17 April 2018 at 14:22:27 UTC, Arafel wrote:
> Hi!
>
> Is there any way to get the full set of templates that are "overloaded" (in my case, based on constraints)?

Currently, there is no way (that I've found, at least) to do this. If you have a workaround, that's great, but there really should be a way - probably __traits(getOverloads). Having __traits(getOverloads) return templates as well should fix some of the issues __traits(getOverloads) has, as a bonus.

--
  Simen
April 19, 2018
On Thursday, 19 April 2018 at 13:57:04 UTC, Simen Kjærås wrote:
> Currently, there is no way (that I've found, at least) to do this. If you have a workaround, that's great, but there really should be a way - probably __traits(getOverloads). Having __traits(getOverloads) return templates as well should fix some of the issues __traits(getOverloads) has, as a bonus.
>

Would it be possible at all? I mean, if the two following codes are equivalent
´´´
    @S("Has foo_A") template foo(string s) if (s == "a") {
        enum foo = "foo_A";
    }
    @S("Has foo_B") template foo(string s) if (s == "b") {
        enum foo = "foo_B";
    }
´´´


´´´
    template foo(string s)
    {
        static if (s == "a")
        {
               @S("Has foo_A") enum foo = "foo_A";
        }
        else static if (s == "b")
        {
              @S("Has foo_B") enum foo = "foo_B";
        }
    }
´´´

How would you define a "template overload"?
And which "overloads" would you like to get if constraints are more general?
And last but not least, the getOverloads is defined on functions, which are callable, whereas templates are not, in general...
April 19, 2018
Well, if that's the lowering, then it's indeed hard. That doesn't mean it shouldn't happen, though... perhaps changing the lowering? I'm no compiles expert, so no idea how).

What I'd like to get is the same that I get using __traits(getMember,...), but repeated n times (AliasSeq perhaps?), like with regular overloads.

Then, whatever I can do with the first entry (the only one I can get currently) should also be possible with the rest. In my case, I'd like to access the UDAs, but I can imagine that the use case that allows us to get a template keeps being valid for all the "hidden" alternatives.

Also, I think that whether to use "getOverloads" or to add a new trait is rather an implementation detail

It's a bit frustrating being able to access only the first of a set...

A.

> Would it be possible at all? I mean, if the two following codes are equivalent
> ´´´
>      @S("Has foo_A") template foo(string s) if (s == "a") {
>          enum foo = "foo_A";
>      }
>      @S("Has foo_B") template foo(string s) if (s == "b") {
>          enum foo = "foo_B";
>      }
> ´´´
>
>
> ´´´
>      template foo(string s)
>      {
>          static if (s == "a")
>          {
>                 @S("Has foo_A") enum foo = "foo_A";
>          }
>          else static if (s == "b")
>          {
>                @S("Has foo_B") enum foo = "foo_B";
>          }
>      }
> ´´´
>
> How would you define a "template overload"?
> And which "overloads" would you like to get if constraints are more general?
> And last but not least, the getOverloads is defined on functions, which are callable, whereas templates are not, in general...
April 19, 2018
On Thursday, 19 April 2018 at 14:16:21 UTC, Alex wrote:
> On Thursday, 19 April 2018 at 13:57:04 UTC, Simen Kjærås wrote:
>> Currently, there is no way (that I've found, at least) to do this. If you have a workaround, that's great, but there really should be a way - probably __traits(getOverloads). Having __traits(getOverloads) return templates as well should fix some of the issues __traits(getOverloads) has, as a bonus.
>>
>
> Would it be possible at all? I mean, if the two following codes are equivalent
> ´´´
>     @S("Has foo_A") template foo(string s) if (s == "a") {
>         enum foo = "foo_A";
>     }
>     @S("Has foo_B") template foo(string s) if (s == "b") {
>         enum foo = "foo_B";
>     }
> ´´´
>
>
> ´´´
>     template foo(string s)
>     {
>         static if (s == "a")
>         {
>                @S("Has foo_A") enum foo = "foo_A";
>         }
>         else static if (s == "b")
>         {
>               @S("Has foo_B") enum foo = "foo_B";
>         }
>     }
> ´´´
>
> How would you define a "template overload"?
> And which "overloads" would you like to get if constraints are more general?
> And last but not least, the getOverloads is defined on functions, which are callable, whereas templates are not, in general...

Your first example defines two templates (which are overloads of the same name), the second only one. There's no ambiguity there.

Since template instantiation is analogous to function calling (though one is a compile-time action, the other a run-time one), talking about template overloads in the same way as function overloads makes perfect sense. Whether the result of instantiating the template is a function, a value, or a type, it's an overload of the template.

--
  Simen
April 19, 2018
On Thursday, 19 April 2018 at 13:57:04 UTC, Simen Kjærås wrote:
> On Tuesday, 17 April 2018 at 14:22:27 UTC, Arafel wrote:
>> Hi!
>>
>> Is there any way to get the full set of templates that are "overloaded" (in my case, based on constraints)?
>
> Currently, there is no way (that I've found, at least) to do this. If you have a workaround, that's great, but there really should be a way - probably __traits(getOverloads). Having __traits(getOverloads) return templates as well should fix some of the issues __traits(getOverloads) has, as a bonus.

https://github.com/dlang/dmd/pull/8195

--
  Simen
April 21, 2018
On Thursday, 19 April 2018 at 17:55:47 UTC, Simen Kjærås wrote:
> Your first example defines two templates (which are overloads of the same name), the second only one. There's no ambiguity there.

So, do you mean, that the constraint belongs to the interface of a template?
April 21, 2018
On Saturday, 21 April 2018 at 11:23:33 UTC, Alex wrote:
> On Thursday, 19 April 2018 at 17:55:47 UTC, Simen Kjærås wrote:
>> Your first example defines two templates (which are overloads of the same name), the second only one. There's no ambiguity there.
>
> So, do you mean, that the constraint belongs to the interface of a template?

Not necessarily - it depends on what you want to achieve. The only thing I mean is that the code clearly defines two templates in one case (and chooses which template to instantiate based on the arguments), and one template in the other (and chooses the contents of that template based on the arguments). Sure, the end result may be similar*, but how it works in the language is clearly defined, and different between the two cases.

*In this case, there are important differences - in the first case the template itself is marked with a UDA, in the second the enum member is. In the first case foo!"c" will fail to instantiate, in the second it won't.

--
  Simen
April 21, 2018
On Saturday, 21 April 2018 at 19:51:05 UTC, Simen Kjærås wrote:
> On Saturday, 21 April 2018 at 11:23:33 UTC, Alex wrote:
>> So, do you mean, that the constraint belongs to the interface of a template?
>
> Not necessarily - it depends on what you want to achieve. The only thing I mean is that the code clearly defines two templates in one case (and chooses which template to instantiate based on the arguments), and one template in the other (and chooses the contents of that template based on the arguments).

This is wrong, at least as I understand this:
Lowering rules apply. These rules define a set of semantic equivalent constructs. I expect all semantic equivalent constructs to be handled equivalent.**


> Sure, the end result may be similar*, but how it works in the language is clearly defined, and different between the two cases.
>
> *In this case, there are important differences - in the first case the template itself is marked with a UDA, in the second the enum member is.
This is a good point. But you won't be able to get the UDA from an uninstantiated template will you? If you will, then, I'm wrong, I think...

** So my point is: If you can transform some construct into another one by lowering rules, than
- either: you can't define an overload
- or: you can define same overloads on both forms.
[1]

> In the first case foo!"c" will fail to instantiate, in the second it won't.

This is due, I didn't add
´´´
else
{
    assert(0);
}
´´´
sorry for this.

[1] http://www.drdobbs.com/architecture-and-design/so-you-want-to-write-your-own-language/240165488?pgno=2
April 22, 2018
On Saturday, 21 April 2018 at 21:10:29 UTC, Alex wrote:
> On Saturday, 21 April 2018 at 19:51:05 UTC, Simen Kjærås wrote:
>> On Saturday, 21 April 2018 at 11:23:33 UTC, Alex wrote:
>>> So, do you mean, that the constraint belongs to the interface of a template?
>>
>> Not necessarily - it depends on what you want to achieve. The only thing I mean is that the code clearly defines two templates in one case (and chooses which template to instantiate based on the arguments), and one template in the other (and chooses the contents of that template based on the arguments).
>
> This is wrong, at least as I understand this:
> Lowering rules apply. These rules define a set of semantic equivalent constructs. I expect all semantic equivalent constructs to be handled equivalent.**

No lowering occurs here. A lowering is when the compiler takes one piece of syntax and replaces it with a different one, usually one that's more verbose.

In a way, it's kind of like a template being instantiated, in that you write some code and it's being replaced by something else. It's not, however, the same thing.

Templates are sort of like compile-time functions - overloads are chosen in a similar way way to how function overloads are chosen, and the result may depend on the parameters given. Two templates, just like two functions, can give the same result without the templates themselves being the same.


>> *In this case, there are important differences - in the first case the template itself is marked with a UDA, in the second the enum member is.
> This is a good point. But you won't be able to get the UDA from an uninstantiated template will you? If you will, then, I'm wrong, I think...

Why not try it?

@("Has foo1_A") template foo1(string s) if (s == "a") {
    enum foo1 = "foo1_A";
}
@("Has foo1_B") template foo1(string s) if (s == "b") {
    enum foo1 = "foo1_B";
}

template foo2(string s)
{
    static if (s == "a")
    {
           @("Has foo2_A") enum foo2 = "foo2_A";
    }
    else static if (s == "b")
    {
          @("Has foo2_B") enum foo2 = "foo2_B";
    }
}

// tuple("Has foo1_A")
pragma(msg, __traits(getAttributes, foo1));
// tuple()
pragma(msg, __traits(getAttributes, foo2));

So yes, we can. Templates are real things and can be manipulated, passed to other templates, etc.

--
  Simen
« First   ‹ Prev
1 2 3