Getting the overload set of a template
Arafel
er.krali at gmail.com
Mon Apr 23 17:46:10 UTC 2018
On Monday, 23 April 2018 at 16:52:11 UTC, Alex wrote:
> On Monday, 23 April 2018 at 16:16:09 UTC, Arafel wrote:
>> ```
>> import std.meta;
>>
>> void main()
>> {
>> pragma(msg, __traits(getMember, A, "Foo1").stringof); //
>> Foo1(int N) if (N & 1)
>> pragma(msg, __traits(getAttributes, __traits(getMember, A,
>> "Foo1"))[0]); // tuple("int", "odd")
>> alias f1a = Instantiate!(__traits(getMember, A, "Foo1"),
>> 1); // This is expected
>> pragma(msg, f1a); // A
>> alias f1b = Instantiate!(__traits(getMember, A, "Foo1"),
>> "+"); // Why would I know that I can even instantiate?? Also,
>> can I haz UDA plz?
>> pragma(msg, f1b); // B
>> }
>>
>> class A {
>> @("int", "odd")
>> template Foo1(int N) if (N & 1) {
>> enum Foo1 = "A";
>> }
>> @("string", "+")
>> template Foo1(string op) if (op == "+") {
>> enum Foo1 = "B";
>> }
>> }
>> ```
>
> I'm not arguing about the case of different interfaces. It is
> more or less ok, as from different argument types it will be
> unambiguous which template will be instantiated. It is the case
> of differentiating templates by their structure and/or
> constraints.
>
> In this case, it is almost sure, that more then one form of
> implementation exists. However, the forms will yield the same
> semantic result. And I'm wondering why the implementation form
> alone leads to differentiation.
Well, with templates the overload resolution must be always
unambiguous:
```
import std.stdio;
void main()
{
pragma(msg, A.Foo1!2);
pragma(msg, A.Foo1!3);
static assert(!is (typeof(A.Foo1!6))); // Compilation failure if
there is any ambiguity
}
class A {
template Foo1(int N) if ((N % 2) == 0) {
enum Foo1 = "A";
}
template Foo1(int N) if ((N % 3) == 0) {
enum Foo1 = "B";
}
}
```
Also, you can try without a constraint, it will still complain.
But you are arguing from the point of view of a hypothetical
semantical equivalence that I don't think it's so clear. Both are
tools that in some cases can lead to the same result, but there
are also cases where they don't math.
You could also argue that function overloads are just
semantically equivalent to a single function with variadic
arguments. Whether the compiler actually lowers it like that or
not should be just an implementation detail, and thus simply not
relevant.
And from a syntactical point of view, it wouldn't make any sense
if the following "overloads" were treated differently:
```
class A {
@("int", "odd")
template Foo1(int N) if (N & 1) {
enum Foo1 = "A";
}
@("int", "even")
template Foo1(int N) if (!(N & 1)) {
enum Foo1 = "B";
}
@("string", "+")
template Foo1(string op) if (op == "+") {
enum Foo1 = "C";
}
@("multi", "string")
template Foo1(T...) if (allSatisfy!(isSomeString, typeof(T)) &&
T.length > 1) {
enum Foo1 = "D";
}
@("multi", "double")
template Foo1(T...) if (allSatisfy!(isFloatingPoint, typeof(T))
&& T.length > 1) {
enum Foo1 = "E";
}
}
```
How would you know which ones are "real" overloads (in your
meaning)?
A.
More information about the Digitalmars-d-learn
mailing list