UDAs - Restrict to User Defined Types?

Nick Sabalausky SeeWebsiteToContactMe at semitwist.com
Thu Nov 8 20:51:29 PST 2012


On Thu, 8 Nov 2012 20:17:24 -0800
"H. S. Teoh" <hsteoh at quickfur.ath.cx> wrote:
> 
> Actually, I just thought of a solution to the whole duck-typing range
> thing:
> 
> 	struct MyRange {
> 		// Self-documenting: this struct is intended to be a
> 		// range.
> 		static assert(isInputRange!MyRange,
> 			"Dude, your struct isn't a range!"); //
> asserts
> 
> 
On Fri, 09 Nov 2012 05:18:59 +0100
"Adam D. Ruppe" <destructionator at gmail.com> wrote:
> 
> Just a note, of course it still wouldn't *force*, but maybe it'd 
> be a good habit to start writing this:
> 
> struct myrange {...}
> static assert(isInputRange!myrange);
> 

Those are only half-solutions as they only prevent false-negatives, not
false-positives. Plus, there's nothing to prevent people from
forgetting to do it in the first place.

I outlined and implemented a proof-of-concept for a full solution
middle of last year:

http://www.semitwist.com/articles/EfficientAndFlexible/MultiplePages/Page5/

The basic gist (and there's definitely still room for plenty of
improvement):

// The General Tool:
string declareInterface(string interfaceName, string thisType)
{
    return `
        // Announce what interface this implements.
        static enum _this_implements_interface_`~interfaceName~`_ =
true;

        // Verify this actually does implement the interface
        static assert(
            is`~interfaceName~`!(`~thisType~`),
            "This type fails to implement `~interfaceName~`"
        );
    `;
}

// Sample usage:
template isFoo(T)
{
    immutable bool isFoo = __traits(compiles,
    (){
        T t;
        static assert(T._this_implements_interface_Foo_);
	t.fooNum = 5;
	int x = t.fooFunc("");
        // Check everything else here
    });
} 

struct MyFoo
{
    // Can probably be more DRY with fancy trickery
    mixin(declareInterface("Foo", "MyFoo"));

    int fooNum;
    int fooFunc(string a) {...}
}

What I'd really like to see is a way to implement declareInterface so
that the isFoo is replaced by an ordinary "interface Foo {...}",
which MyFoo's members are automatically checked against. I suspect that
should be possible with some fancy metaprogramming-fu.



More information about the Digitalmars-d mailing list