// SAMPLE CONSTRAINTS
//=============================================================

constraint CInputRange
{
        static assert (is(typeof(
        {
                typeof(this) r = void;
                if (r.empty) {}
                r.popFront();
                auto h = r.front;
        })));
}

constraint CForwardRange : CInputRange
{
        static assert (is(typeof(
        {
                typeof(this) r1 = void;
                typeof(this) r2 = r1.save;
        })));
}

constraint CBidirectionalRange : CForwardRange
{
        static assert (is(typeof(
        {
                typeof(this) r = void;
                r.popBack();
                auto t = r.back;
                auto w = r.front;
                static assert(is(typeof(t) == typeof(w)));
        })));
}

constraint CRandomAccessRange : CBidirectionalRange
        if (!isInfinite!typeof(this))
{
        static assert (is(typeof(
        {
                typeof(this) r = void;
                auto e = r[1];
        })));
        static assert(hasLength!typeof(this));
    static assert(!isNarrowString!typeof(this));
}

constraint CRandomAccessRange : CForwardRange
        if (isInfinite!typeof(this))
{
        static assert (is(typeof(
        {
                typeof(this) r = void;
                auto e = r[1];
        })));
}

// SAMPLE USAGES
//=========================================================

struct InputRange : CInputRange // Apply constraint to a struct
{
        ....
}

struct ForwardRange // Do not apply any constraint but implement a ForwardRange
{
        ....
}

interface IBidirectionalRange : CBidirectionalRange // Apply constraint to the classes derived from IBidirectionalRange
{
        ....
}

class BidirectionalRange : IBidirectionalRange // Implement BidirectionalRange and apply constraint CBidirectionalRange
{
        ...
}

struct RandomAccessFinite : CRandomAccessRange
{
        ...
}

struct RandomAccessInfinite : CRandomAccessRange
{
        ...
}

//-----------------------------------------------------------

void foo(Range : CInputRange)(Range r) { }         // (1)
void foo(Range : CForwardRange)(Range r) { }       // (2)
void foo(Range : CBidirectionalRange)(Range r) { } // (3)
void foo(Range : CRandomAccessRange)(Range r) { }  // (4)

//-----------------------------------------------------------

void main()
{
        InputRange ir;
        ForwardRange fr;
        auto br = new BidirectionalRange();
        RandomAccessFinite rfr;
        RandomAccessInfinite rir;
        
        foo(ir);  // calls (1)
        foo(fr);  // calls (2)
        foo(br);  // calls (3)
        foo(rfr); // calls (4)
        foo(rir); // calls (4)
}

Reply via email to