//====================================================
//==                   OR                          ===
//====================================================


template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    {
        R r = void;       // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range
    }));
}

template isJustInputRange(R)
{
enum bool isJustInputRange = isInputRange!R && !isForwardRange!R;
}

template isForwardRange(R)
{
    enum bool isForwardRange = isInputRange!R && is(typeof(
    {
        R r1 = void;
        R r2 = r1.save; // can call "save" against a range object
    }));
}

template isJustForwardRange(R)
{
enum bool isJustForwardRange = isForwardRange!R && !isBidirectionalRange!R && !isRandomAccessRange!R;
}

template isBidirectionalRange(R)
{
enum bool isBidirectionalRange = isForwardRange!R && is(typeof(
    {
        R r = void;
        r.popBack();
        auto t = r.back;
        auto w = r.front;
        static assert(is(typeof(t) == typeof(w)));
    }));
}

template isJustBidirectionalRange(R)
{
enum bool isJustBidirectionalRange = isBidirectionalRange!R && !isRandomAccessRange!R;
}

template isRandomAccessRange(R)
{
    enum bool isRandomAccessRange = is(typeof(
    {
        static assert(isBidirectionalRange!R ||
                      isForwardRange!R && isInfinite!R);
        R r = void;
        auto e = r[1];
        static assert(!isNarrowString!R);
        static assert(hasLength!R || isInfinite!R);
    }));
}

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

struct InputRange
{
        ....
        static assert (isInputRange!InputRange);
}

struct ForwardRange
{
        ....
        static assert (isForwardRange!ForwardRange);
}

interface IBidirectionalRange
{
        ....
        // static assert (isBidirectionalRange!IBidirectionalRange);
        // can not be used in interfaces
}

class BidirectionalRange : IBidirectionalRange
{
        ...
        static assert (isBidirectionalRange!BidirectionalRange);        
}

struct RandomAccessFinite
{
        ...
        static assert (isRandomAccessRange!RandomAccessFinite);
}

struct RandomAccessInfinite
{
        ...
        static assert (isRandomAccessRange!RandomAccessInfinite);
}

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

void foo(Range)(Range r) if (isJustInputRange!Range) { }
void foo(Range)(Range r) if (isJustForwardRange!Range) { }
void foo(Range)(Range r) if (isJustBidirectionalRange!Range) { }
void foo(Range)(Range r) if (isRandomAccessRange!Range) { }

Reply via email to