Implicit enum conversions are a stupid PITA
Marianne Gagnon
auria.mg at gmail.com
Tue Mar 23 15:39:06 PDT 2010
Nick Sabalausky Wrote:
> I'm bringing this over here from a couple separate threads over on "D.learn"
> (My "D1: Overloading across modules" and bearophile's "Enum equality test").
>
> Background summary:
>
> bearophile:
> > I'm looking for D2 rough edges. I've found that this D2 code
> > compiles and doesn't assert at runtime:
> >
> > enum Foo { V1 = 10 }
> > void main() {
> > assert(Foo.V1 == 10);
> > }
> >
> > But I think enums and integers are not the same type,
> > and I don't want to see D code that hard-codes comparisons
> > between enum instances and number literals, so I think an
> > equal between an enum and an int has to require a cast:
> >
> > assert(cast(int)(Foo.V1) == 10); // OK
>
> He goes on to mention C++0x's "enum class" that, smartly, gets rid of that
> implicit conversion nonsense.
>
> To put it simply, I agree with this even on mere principle. I'm convinced
> that the current D behavior is a blatant violation of strong-typing and
> smacks way too much of C's so-called "type system".
>
> But here's another reason to get rid it that I, quite coincidentally,
> stumbled upon right about the same time:
>
> Me:
> > In D1, is there any reason I should be getting an error on this?:
> >
> > // module A:
> > enum FooA { fooA };
> > void bar(FooA x) {}
> >
> > // module B:
> > import A;
> > enum FooB { fooB };
> > void bar(FooB x) {}
> >
> > bar(FooB.fooB); // Error: A.bar conflicts with B.bar (WTF?)
>
> In the resulting discussion (which included a really hackish workaround), it
> was said that this is because of a rule (that I assume exists in D2 as well)
> that basically goes "two functions from different modules are in conflict if
> they have the same name." I assume (and very much hope) that the rule also
> has a qualification "...but only if implicit conversion rules make it
> possible for one to hijack the other".
>
> It was said that this is to prevent a function call from getting hijacked by
> merely importing a module (or making a change in an imported module). That I
> can completely agree with. But I couldn't understand why this would cause
> conflicts involving enums until I thought about implicit enum-to-base-type
> conversion and came up with this scenario:
>
> // Module Foo:
> enum Foo { foo }
>
> // module A:
> import Foo;
> void bar(Foo x){}
>
> // module B version 1:
> import Foo; // Note: A is not imported yet
> void bar(int x){}
> bar(Foo.foo); // Stupid crap that should never be allowed in the first place
>
> // module B version 2:
> import Foo;
> import A; // <- This line added
> void bar(int x){}
> bar(Foo.foo); // Now that conflict error *cough* "helps".
>
> So thanks to the useless and dangerous ability to implicitly convert an enum
> to its base type, we can't have certain perfectly sensible cross-module
> overloads.
>
> Although, frankly, I *still* don't see why "bar(SomeEnum)" and
> "bar(SomeOtherEnum)" should ever be in conflict (unless that's only D1, or
> if implicit base-type-to-enum conversions are allowed (which would make
> things even worse)).
>
>
Hum...
+1
What can I add, you said it all ;)
More information about the Digitalmars-d
mailing list