DIPX: Enum Literals / Implicit Selector Expression

Steven Schveighoffer schveiguy at gmail.com
Fri Jul 1 19:37:46 UTC 2022


On 7/1/22 2:32 PM, Walter Bright wrote:
> On 7/1/2022 8:42 AM, Steven Schveighoffer wrote:
>> How I would design it:
> 
> Those are reasonable suggestions.
> 
> But just let me throw this out. I've heard from many sources that nobody 
> understands C++ function overloading. It is described with pages of 
> detail in the Standard. Even compiler writers only *temporarily* 
> understand it while they are implementing it.
> 
> How C++ programmers deal with it is they randomly try things until it 
> works.

This is why I'm asking the questions. I don't have experience on how to 
implement function overloading, and I don't know what pitfalls might be 
introduced from doing something like this.

> D's overloading is simpler than C++'s. But it gets more complex all the 
> time. For example, named arguments make it more complicated.
> 
> To add more complexity would take a really really strong benefit.

There's 2 questions to answer here:

1) is it possible and feasible?
2) do we want to add to the complexity of the language?

Obviously if 1 is false, it's a non-starter. And it looks like you have 
indirectly answered that it is possible.

So on to 2:

IMO, I think the language benefits greatly from little syntax tricks 
like this. `foreach` is a great improvement over `for`. omitting 
parentheses can cause problems, but in general makes things far more 
pleasant to write/read.

I also have experience using a language (Swift) which has this feature, 
and it's really really nice, especially when dealing with verbose enums.

When using D enums after using Swift, I get the same feeling I do when I 
use C# or C++ after experiencing D metaprogramming. It feels like the D 
compiler knows all the information to make this simple, it just is 
asking me to jump through a few more hoops than it should.

I am genuinely curious why this will add too much to the complexity of 
overloading.

The current rules are:

1. no match
2. match with implicit conversions
3. match with qualifier conversion (if the argument type is 
qualifier-convertible to the parameter type)
4. exact match

That shouldn't change.

The next part says:

    Each argument (including any this reference) is compared against the 
function's corresponding parameter to determine the match level for that 
argument. The match level for a function is the worst match level of 
each of its arguments.

OK, so a #value expression would be an "exact match" of any enum type 
that contains all the value literals in that expression, and a a "no 
match" for any other situation. The rest of the rules would apply as-is, 
including partial ordering, etc.

Since enums are not related, they should be completely distinct in terms 
of partial ordering.

Am I misunderstanding something?

> 
> BTW, if you really want a specific case to work:
> 
>      enum A { a, b, c }
>      alias a = A.a;
>      alias b = A.b;
>      alias c = A.c;
> 
> This could probably be automated with metaprogramming.

This doesn't scale well.

```d
enum A { a, b, c }
alias a = A.a;
alias b = A.b;
alias c = A.c;

void bar(A a) {}

void foo()
{
    int a = 5;
    bar(a); // error;
}

--- mod2.d:
import mod1;
int a = 5;
void foo()
{
    bar(.a); // error;
}
```

And I also have used `with` statements, which *mostly* works, but I've 
come across some head-scratching problems when naming conflicts occur.

-Steve


More information about the Digitalmars-d mailing list