Concepts? Template specialization depending on class functions?

Sean Kelly sean at f4.ca
Thu Mar 2 14:17:49 PST 2006


Walter Bright wrote:
> "Ben Phillips" <Ben_member at pathlink.com> wrote in message 
> news:du751p$1imp$1 at digitaldaemon.com...
>> One idea I've heard is to use
>> "concepts" (a possible
>> extension to C++) where code would go as follows
> 
> Concepts are an interesting idea. As far as I know, nobody has implemented 
> it for C++ so nobody knows if it really works or not. 

Now that static if is ignored for template expansion, concepts aren't as 
necessary as they once were.  For example, this is how I'd have 
implemented concepts in D before, which is fairly close to how it would 
be done in C++:

     struct DoesNiftyThingA {}
     struct DoesNiftyThingB {}
     struct DoesntDoAnything {}

     template testFeatures( T )
     {
         static if( /* test for A */ )
             alias DoesNiftyThingA testFeatures;
         else static if( /* test for B */ )
             alias DoesNiftyThingB testFeatures;
         else
             alias DoesntDoAnything testFeatures;
     }

     // specialization for A
     template conceptFn( T, T1 : DoesNiftyThingA = testFeatures!(T) )
     {
         static assert( is(testFeatures!(T) == DoesNiftyThingA );
         void conceptFn() {}
     }

     // specialization for B
     template conceptFn( T, T1 : DoesNiftyThingB = testFeatures!(T) )
     {
         static assert( is(testFeatures!(T) == DoesNiftyThingB );
         void conceptFn() {}
     }

     // default implementation
     template conceptFn( T )
     {
         static assert( is(testFeatures!(T) == DoesNiftyThingB );
         void conceptFn() {}
     }

But using the template parameter list is unwieldy and error-prone (this 
the static asserts).  However, the equivalent now could be:

     template conceptFn( T )
     {
         static if( /* test for A */ )
             void conceptFn() {}
         else static if( /* test for B */ )
             void conceptFn() {}
         else
             void conceptFn() {}
     }

And pragmas make it fairly easy to provide meaningful error messages if 
there is no default:

     template conceptFn( T )
     {
         static if( /* test for A */ )
             void conceptFn() {}
         else static if( /* test for B */ )
             void conceptFn() {}
         else
         {
             pragma( msg, "conceptFn is not defined for this type." );
             static assert( false );
         }
     }

Coupled with Don's template string magic, it should be fairly simple to 
improve the error message to include the supplied type name, etc.

So... while I think concepts may still be nice to have, I'm not sure 
there's a pressing need for them any longer.  In fact, I think I'm going 
to go back and rewrite my template code to use the "static if" method 
above, as most of it still uses the old C++ style.


Sean



More information about the Digitalmars-d mailing list