From e788152c13de8929d4c368929ea743a2885741e5 Mon Sep 17 00:00:00 2001 From: Colden Cullen Date: Sat, 16 Aug 2014 16:50:09 -0700 Subject: [PATCH] Updated documentation, README.md --- README.md | 48 +++++++++++++++++++++++++++++++++++-------- source/quack/mixins.d | 6 +++--- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 88d496a..e716f0c 100644 --- a/README.md +++ b/README.md @@ -7,32 +7,64 @@ A library for enabling compile-time duck typing in D. #### Duck Typing -Duck typing is a reference to the phrase "if it walks like a duck, and quacks like a duck, then it's probably a duck." The idea is that if a `struct` or `class` has all the same members as another, it should be usable as the other. +Duck typing is a reference to the phrase "if it walks like a duck, and quacks +like a duck, then it's probably a duck." The idea is that if a `struct` or +`class` has all the same members as another, it should be usable as the other. + +#### Usage + +Duck exists so that you may treat non-related types as polymorphic, at compile +time. There are two primary ways to use quack: + +1) Taking objects as arguments: For this, you should use `extends!( A, B )`, +which returns true if A "extends" B. It can do this by implementing all of the +same members B has, or by having a variable of type B that it has set to +`alias this`. + +2) Storing pointers to objects: For this, you should use a `DuckPointer!A`, +which can be created with `duck!A( B b )`, assuming B "extends" A (the actual +check is done using `extends`, so see the docs on that). Note that this approach +should only be used when you need to actually store the object, as it is much +slower than the pure template approach. #### Examples ```d import quack; +import std.stdio; -struct A +struct Base { int x; } -struct B +struct Child1 +{ + Base b; + alias b this; +} + +struct Child2 { - A a; - alias a this; + int x; } -void someFunction( T )( T t ) if( extends!( T, A ) ) +void someFunction( T )( T t ) if( extends!( T, Base ) ) { + writeln( t.x ); +} +struct HolderOfBase +{ + DuckPointer!Base myBase; } void main() { - B b; - someFunction( b ); + someFunction( Child1() ); + someFunction( Child2() ); + + auto aHolder1 = new HolderOfA( duck!Base( Child1() ) ); + auto aHolder2 = new HolderOfA( duck!Base( Child2() ) ); } ``` diff --git a/source/quack/mixins.d b/source/quack/mixins.d index ec6403f..202ff64 100644 --- a/source/quack/mixins.d +++ b/source/quack/mixins.d @@ -43,16 +43,16 @@ template hasTemplateMixin( Child, alias mix ) * Returns: * Whether Child has all the members of mix. */ -template hasStringMixin( Base, string mix ) +template hasStringMixin( Child, string mix ) { - static if( isExtendable!Base ) + static if( isExtendable!Child ) { struct MixinImpl { mixin( mix ); } - enum hasStringMixin = hasSameMembers!( Base, MixinImpl ); + enum hasStringMixin = hasSameMembers!( Child, MixinImpl ); } else {