C++ guys hate static_if?

deadalnix deadalnix at gmail.com
Wed Mar 13 03:22:52 PDT 2013


On Tuesday, 12 March 2013 at 16:59:41 UTC, H. S. Teoh wrote:
> On Tue, Mar 12, 2013 at 12:28:07PM -0400, Nick Sabalausky wrote:
>> On Tue, 12 Mar 2013 16:02:24 +0100
>> "TommiT" <tommitissari at hotmail.com> wrote:
>> 
>> > On Tuesday, 12 March 2013 at 13:44:35 UTC, Nick Sabalausky 
>> > wrote:
>> > > On Tue, 12 Mar 2013 12:51:03 +0100
>> > > "TommiT" <tommitissari at hotmail.com> wrote:
>> > >
>> > >> On Tuesday, 12 March 2013 at 02:39:06 UTC, TommiT wrote:
>> > >> > struct S1 implements A2 {
>> > >> >     void foo() { }
>> > >> >     void bar() { }
>> > >> > }
>> > >> 
>> > >> That's not good. Types shouldn't have to explicitly say 
>> > >> that they implement a concept.
>> > >
>> > > I *strongly* disagree. A much as I love ranges (for 
>> > > example),
>> > > their duckiness is the one thing I consider to be a huge 
>> > > mistake.
>> > 
>> > The problem with having to explicitl specify that a type 
>> > implements a certain concept, is the resulting strong 
>> > coupling between the concept definition and the type. This 
>> > prevents "happy accidents" like the following from happening:
>> > 
>> > Alice and Bob write libraries without knowing anything about 
>> > each other or each other's code. Alice implements the 
>> > following in her library:
>> > 
>> > concept IntegerLike {
>> >      ...
>> > }
>> > 
>> > void foo(IntegerLike N)(N n) { }
>> > 
>> > Bob implements the following in his library:
>> > 
>> > struct SafeInt {
>> >      ...
>> > }
>> > 
>> > Later Bob realizes that Alice has written this cool function 
>> > foo which accepts his type SafeInt as an argument because 
>> > SafeInt just so happens to fulfill the requirements of the 
>> > IntegerLike concept defined in Alice's library.
>> > 
>> > Although, the majority of concepts should come from the 
>> > standard library.
>> 
>> "Happy accidents" is nothing more than another way of saying 
>> "Shit
>> fucked up, but by pure dumb luck there was no damage". It's an
>> absolutely *terrible* thing to encourage and design for. You 
>> may as
>> well just go dynamic all the way, a la ActionScript 2 or 
>> Python - it's
>> all the same "let random things happen by accident and blindly 
>> hope it
>> just happens to turn out correct" philosophy.
>> 
>> Design-by-accident is an anti-pattern.
>> 
>> To me more specific, the problem with duck typing is that it 
>> falsely
>> assumes that name+signature uniquely defines semantics (which 
>> is
>> clearly not a valid assumption). Avoiding accidental screwups 
>> under
>> duck typing *is* feasible if there's only a few well-known 
>> duck types
>> that are ever in play (ex: our entire list of available duck 
>> types is
>> a handful of phobos-defined ranges and basically nothing 
>> else). But it
>> does not scale: The likelihood of accidental fuckups is 
>> multiplied
>> with each additional duck type in existence, with non-stdlib 
>> duck
>> types carrying a greater "accidental fuck up" weight.
>
> I see it from another perspective: I've had to deal with 
> proprietary
> libraries that defined types that couldn't be used with a 
> particular
> container type, just because the container type expects the 
> item type to
> implement a particular interface, but it doesn't. But actually, 
> it
> *does* have the requisite members to implement that interface; 
> it just
> didn't *say* it implemented that interface. So there's the need 
> for Yet
> Another Useless Java-style Wrapper Class just to work around 
> this
> nonsense. Duck-typing solves this problem.
>
> Of course, full-out ducktyping has its own problems, like you 
> said; but
> there needs to be a way of rewriting APIs such that you could 
> say "type
> T doesn't implement interface I right now, but actually, if you 
> rewrite
> T.A to T.X and T.B to T.Y, then T implements interface I just 
> fine".
> Though with D, I suspect this may actually be possible via 
> alias this:
>
> 	struct RewireInterface(T, Interface, Tuple!(string,string)... 
> rewrites)
> 	{
> 		T t;
> 		alias t this;
> 		foreach (rewrite; rewrites) {
> 			alias rewrite[0] = rewrite[1];
> 		}
> 	}
>
> OK, maybe not. But the foreach could be replace with a suitable
> recursive template so that the generated aliases are at the 
> top-level in
> RewireInterface. Probably some other hack is needed to work 
> around the
> need for Tuple in the compile-time parameters, which I'm pretty 
> sure DMD
> rejects right now. But assuming all this can be worked around, 
> you could
> do something like this:
>
> 	struct StraitJacketedProprietaryItem {
> 		int propX() { ... }
> 		int propY() { ... }
> 	}
>
> 	concept MyInterface {
> 		int myX();
> 		int myY();
> 	}
>
> 	alias NonStraitJacketedItem = RewireInterface!(
> 		StraitJacketedProprietaryItem, MyInterface,
> 		"myX", "propX",
> 		"myY", "propY"
> 	);
>
> 	assert(NonStraitJacketedItem implements MyInterface);
>
> OK, lots of pseudo-code going on here, but you get the idea.
>
>
> T

D current compile time capabilities already allow this kind of 
stuff. I don't see concept as a good idea to introduce into D 
right now, but definitively something to look at for the future.


More information about the Digitalmars-d mailing list