May 09, 2012
// 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)
}

May 09, 2012
// implement foo's without constraints
//------------------------------------------------------------

void foo(Range)(Range r)
	if (isInputRange!Range && !isForwardRange!Range)
{ }

void foo(Range)(Range r)
	if (isForwardRange!Range && !isBidirectionalRange!Range &&
!isRandomAccessRange!Range)
{ }

void foo(Range)(Range r)
	if (isBidirectionalRange!Range && !isRandomAccessRange!Range)
{ }

void foo(Range)(Range r)
	if (isRandomAccessRange!Range)
{ }

May 09, 2012
Idea is simple: we need same constraints on "implementation" and "argument deduction. Syntax may change.
May 09, 2012
Sorry I mean "template specialization" instead of "argument deduction".
May 09, 2012
We can already kind of do what you're asking without a language feature. For instance, if you want to define that something is a type of range...

struct MyRange { ... }

static assert(isInputRange!MyRange); // won't compile unless MyRange is an input range

On Wednesday, 9 May 2012 at 15:04:51 UTC, İbrahim Gökhan YANIKLAR wrote:
> // implement foo's without constraints
> //------------------------------------------------------------
>
> void foo(Range)(Range r)
> 	if (isInputRange!Range && !isForwardRange!Range)
> { }
>
> void foo(Range)(Range r)
> 	if (isForwardRange!Range && !isBidirectionalRange!Range &&
> !isRandomAccessRange!Range)
> { }
>
> void foo(Range)(Range r)
> 	if (isBidirectionalRange!Range && !isRandomAccessRange!Range)
> { }
>
> void foo(Range)(Range r)
> 	if (isRandomAccessRange!Range)
> { }

And these could certainly use some library sugar. How about this:

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

template isJustForwardRange(R) ...etc...


May 09, 2012
Allways we have some ways to do somethings.
The question is: which is better, easier and understandable.
I think my proposal is better.


> And these could certainly use some library sugar. How about this:
>
> template isJustInputRange(R) {
>     enum bool isJustInputRange = isInputRange!R && !isForwardRange!R;
> }

If we add for example isBufferedInputRange, we have to change isJustInputRange too. It's not a general solution.
May 09, 2012
what is the huge difference between D's current concepts - except that your idea allows to derive from concepts?

http://dlang.org/concepts.html
May 09, 2012
There is not a huge difference, but this idea can be extended.
After your reply, I have found this proposal for C++.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf


On Wednesday, 9 May 2012 at 16:40:24 UTC, dennis luehring wrote:
> what is the huge difference between D's current concepts - except that your idea allows to derive from concepts?
>
> http://dlang.org/concepts.html

May 09, 2012
We can not write a common interface for classes and structs. Concepts or constraints can provide that.
May 09, 2012
Am 09.05.2012 19:07, schrieb "İbrahim Gökhan YANIKLAR" <yanikibo@gmail.com>":
> We can not write a common interface for classes and structs.
> Concepts or constraints can provide that.

we can write a common interface for both - but not a contract checking one
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home