Differing levels of type-inference: Can D do this?

Chad J chadjoan at __spam.is.bad__gmail.com
Sun Jul 29 10:11:17 PDT 2012


On 07/29/2012 08:32 AM, Simen Kjaeraas wrote:
> On Sat, 28 Jul 2012 22:47:01 +0200, Chad J
> <chadjoan at __spam.is.bad__gmail.com> wrote:
>
>
>> isInputRange!___ r2 = [1,2,3].some.complex.expression();
>>
>> It doesn't make sense. isInputRange!() isn't a type, so how do I
>> constrain what type is returned from some arbitrary expression?
>>
>> So far the only way I know how to do this is to pass it through a
>> template and use template constraints:
>>
>> auto makeSureItsARange(T)(T arg) if ( isInputRange!T )
>> {
>> return arg;
>> }
>>
>> auto r2 = makeSureItsARange([1,2,3].some.complex.expression());
>>
>> however, the above is unreasonably verbose and subject to naming whimsy.
>
>
> import std.typetuple : allSatisfy;
>
> template checkConstraint( T ) {
> template checkConstraint( alias Constraint ) {
> enum checkConstraint = Constraint!T;
> }
> }
>
>
> template constrain( T... ) {
> auto constrain( U, string file = __FILE__, int line = __LINE__ )( auto
> ref U value ) {
> static assert( allSatisfy!( checkConstraint!U, T ), "Type " ~ U.stringof
> ~ " does not fulfill the constraints " ~ T.stringof );
> return value;
> }
> }
>
> version (unittest) {
> import std.range : isInputRange, ElementType;
>
> template hasElementType( T ) {
> template hasElementType( U ) {
> enum hasElementType = is( ElementType!U == T );
> }
> }
> }
> unittest {
> assert( __traits( compiles, { int[] a = constrain!isInputRange( [1,2,3]
> ); } ) );
> assert( !__traits( compiles, { int a = constrain!isInputRange( 2 ); } ) );
> assert( __traits( compiles, { int[] a = constrain!(isInputRange,
> hasElementType!int)( [1,2,3] ); } ) );
> assert( __traits( compiles, { string a = constrain!(isInputRange,
> hasElementType!dchar)( "abc" ); } ) );
> assert( !__traits( compiles, { string a = constrain!(isInputRange,
> hasElementType!dchar)( "abc"w ); } ) );
> }
>
>
> So there. Now, you simply use auto a = constrain!isInputRange(
> expression );. Is this what you wanted?
>

That's pretty good.  It's still not as concise or easy to discover as 
the language's natural syntax for type declarations, but it's the kind 
of thing I'd use for my own purposes as a trick to get around language 
limitations.


More information about the Digitalmars-d-learn mailing list