www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Andrei's interface requests

reply Christopher Wright <dhasenan gmail.com> writes:
Andrei has put up a few enhancement requests in the bugzilla:
http://d.puremagic.com/issues/show_bug.cgi?id=2784
http://d.puremagic.com/issues/show_bug.cgi?id=2785
http://d.puremagic.com/issues/show_bug.cgi?id=2786

These are intended to change interfaces from being solely a tool of 
polymorphism into a way of specifying type constraints. The additions 
recommended can only be used at compile time (constructors, static 
functions, and nested types).

I grant that it would be quicker and clearer to write:
interface Foo
{
    static void stuff();
    this (int);
}
template Template(Arg : Foo) {}

than to write:
template Template(Arg) if (is (typeof (new Arg(0)) && 
isStaticFunction!(Arg, "stuff")) {}

However, I'm not sure whether this would be used much at all, and it 
deserves some discussion.


interface Foo
{
     extern void bar(int, Foo, double);
}

meaning that a non-member function bar should exist that accepts an int, 
*the implementor of Foo*, and a double.

This is a huge and silent divergence from the standard meaning of using 
the interface name; it would allow:
class C : Foo
{
	static void bar(int, C, double);
}

and disallow:
class C : Foo
{
	static void bar(int, Foo, double);
}

Thoughts? Any concerns that I have not raised? I don't do sufficient 
metaprogramming to find any of this useful, I admit.
Apr 03 2009
next sibling parent Jason House <jason.james.house gmail.com> writes:
2786 also mentions struct using interfaces... I take it Andrei has come around
on that.

I think I'd prefer for polymorphic and static/struct interfaces to be distinct
from each other.

I also agree that 2785 introduces a dangerous construct when mixed with normal
interfaces. 


Christopher Wright Wrote:

 Andrei has put up a few enhancement requests in the bugzilla:
 http://d.puremagic.com/issues/show_bug.cgi?id=2784
 http://d.puremagic.com/issues/show_bug.cgi?id=2785
 http://d.puremagic.com/issues/show_bug.cgi?id=2786
 
 These are intended to change interfaces from being solely a tool of 
 polymorphism into a way of specifying type constraints. The additions 
 recommended can only be used at compile time (constructors, static 
 functions, and nested types).
 
 I grant that it would be quicker and clearer to write:
 interface Foo
 {
     static void stuff();
     this (int);
 }
 template Template(Arg : Foo) {}
 
 than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) && 
 isStaticFunction!(Arg, "stuff")) {}
 
 However, I'm not sure whether this would be used much at all, and it 
 deserves some discussion.
 

 interface Foo
 {
      extern void bar(int, Foo, double);
 }
 
 meaning that a non-member function bar should exist that accepts an int, 
 *the implementor of Foo*, and a double.
 
 This is a huge and silent divergence from the standard meaning of using 
 the interface name; it would allow:
 class C : Foo
 {
 	static void bar(int, C, double);
 }
 
 and disallow:
 class C : Foo
 {
 	static void bar(int, Foo, double);
 }
 
 Thoughts? Any concerns that I have not raised? I don't do sufficient 
 metaprogramming to find any of this useful, I admit.
Apr 03 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Christopher Wright wrote:
 Andrei has put up a few enhancement requests in the bugzilla:
 http://d.puremagic.com/issues/show_bug.cgi?id=2784
 http://d.puremagic.com/issues/show_bug.cgi?id=2785
 http://d.puremagic.com/issues/show_bug.cgi?id=2786
Yah, this too: http://d.puremagic.com/issues/show_bug.cgi?id=2050
 These are intended to change interfaces from being solely a tool of 
 polymorphism into a way of specifying type constraints. The additions 
 recommended can only be used at compile time (constructors, static 
 functions, and nested types).
Yah. Let me add that I haven't thought the changes through, but I posted them to foster discussion, which is happening (thanks!).
 I grant that it would be quicker and clearer to write:
 interface Foo
 {
    static void stuff();
    this (int);
 }
 template Template(Arg : Foo) {}
 
 than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) && 
 isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many of us can instantly figure how the former works, whereas the latter is thoroughly obscure. Let me also pull the definition of a couple of range types in std.range (by the way, I should commit the new Phobos today): template isInputRange(R) { enum bool isInputRange = is(typeof( { R r; // can define a range object if (r.empty) {} // can test for empty r.next; // can invoke next auto h = r.head; // can get the head of the range }())); } I wrote it as clearly as I could, and it doesn't quite look that pretty. I didn't even know the typeof({ ... }()) trick is possible; I saw it somewhere on this group, and took to it. Otherwise the code would have been even more convoluted (along the lines of what you wrote, just more of it). Furthermore, if a type is not a range, there's no simple way to output an error message telling exactly which test if failed. The only test possible is e.g. isInputRange!MyType. I think we can't quite be happy that this is D's offering with regard to concepts. On the other hand, we'd like to avoid the aggravation of C++ concepts, which, in my humble opinion, have a very low power/complexity ratio. So I wanted to look at how interfaces can be reasonably extended into expressing concepts while still being strongly integrated with their classic runtime polymorphic role.
 However, I'm not sure whether this would be used much at all, and it 
 deserves some discussion.
 

 interface Foo
 {
     extern void bar(int, Foo, double);
 }
 
 meaning that a non-member function bar should exist that accepts an int, 
 *the implementor of Foo*, and a double.
 
 This is a huge and silent divergence from the standard meaning of using 
 the interface name; it would allow:
 class C : Foo
 {
     static void bar(int, C, double);
 }
 
 and disallow:
 class C : Foo
 {
     static void bar(int, Foo, double);
 }
 
 Thoughts? Any concerns that I have not raised? I don't do sufficient 
 metaprogramming to find any of this useful, I admit.
I thought of that, too. One option is to parameterize Foo with its subtype's name: interface Foo(X) { extern void bar(int, X, double); } Then you'd require C : Foo!C and so on. I'm not sure how important this detail is, but it is worth thinking of. Another issue is that constructors in a struct are one thing, whereas in a class they are quite a different thing (references of a class can be copied!) Andrei
Apr 03 2009
next sibling parent reply Kagamin <spam here.lot> writes:
Andrei Alexandrescu Wrote:

 I grant that it would be quicker and clearer to write:
 interface Foo
 {
    static void stuff();
    this (int);
 }
 template Template(Arg : Foo) {}
 
 than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) && 
 isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many of us can instantly figure how the former works, whereas the latter is thoroughly obscure.
1. If template constraints suck, why not fixing *them*? 2. If implementation not complaining to interface constrains is prohibited, why you would want template constraints at all? Just use features you want and compiler will give errors if they are not provided. 3. If you use templates, why you would need interfaces at all? Interfaces parameterised with their implementations!
Apr 04 2009
next sibling parent Kagamin <spam here.lot> writes:
Kagamin Wrote:

 1. If template constraints suck, why not fixing *them*?
There were so many proposals... For example my :) compile time reflection api will be much more flexible and readable than any declarational syntax and with it you can throw away that declarational burden from parser.
Apr 04 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 04 Apr 2009 16:49:23 +0400, Kagamin <spam here.lot> wrote:

 Andrei Alexandrescu Wrote:

 I grant that it would be quicker and clearer to write:
 interface Foo
 {
    static void stuff();
    this (int);
 }
 template Template(Arg : Foo) {}

 than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) &&
 isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many of us can instantly figure how the former works, whereas the latter is thoroughly obscure.
1. If template constraints suck, why not fixing *them*?
I believe his proposal exactly intends to fix them.
 2. If implementation not complaining to interface constrains is  
 prohibited, why you would want template constraints at all? Just use  
 features you want and compiler will give errors if they are not provided.
 3. If you use templates, why you would need interfaces at all?

 Interfaces parameterised with their implementations!
Apr 04 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Kagamin wrote:
 Andrei Alexandrescu Wrote:
 
 I grant that it would be quicker and clearer to write:
 interface Foo
 {
    static void stuff();
    this (int);
 }
 template Template(Arg : Foo) {}

 than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) && 
 isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many of us can instantly figure how the former works, whereas the latter is thoroughly obscure.
1. If template constraints suck, why not fixing *them*?
That's a fix.
 2. If implementation not complaining to interface constrains is prohibited,
why you would want template constraints at all? Just use features you want and
compiler will give errors if they are not provided.
Experience with C++ has shown that template functions tend to bite too much, i.e. they accept an argument and then they reject it when compiling. This makes overloading with templates very difficult.
 3. If you use templates, why you would need interfaces at all?
 
 Interfaces parameterised with their implementations!
I don't get this. Andrei
Apr 04 2009
parent reply Kagamin <spam here.lot> writes:
Andrei Alexandrescu Wrote:

 1. If template constraints suck, why not fixing *them*?
That's a fix.
This is a fix to interfaces, not to template constraints. If template constraints fail to serve their purpose, what are they for? Make them work, not others to work for them.
Apr 04 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Kagamin wrote:
 Andrei Alexandrescu Wrote:
 
 1. If template constraints suck, why not fixing *them*?
That's a fix.
This is a fix to interfaces, not to template constraints. If template constraints fail to serve their purpose, what are they for? Make them work, not others to work for them.
This is a change to interfaces to allow them to be used in place of template constraints in many circumstances. The idea is that the syntax of template constraints is sufficiently obtuse that you need to use idioms to get around it: template AcceptableToTemplate(T) { static if (...) // check for non-existence of property 1 { alias void AcceptableToTemplate; } else static if (...) // check for non-existence of property 2 { alias void AcceptableToTemplate; } else { alias T AcceptableToTemplate; } } template Template (T : AcceptableToTemplate!(T)) {} Using that, it's difficult to determine what types you can pass to Template.
Apr 04 2009
prev sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 04 Apr 2009 01:13:09 +0400, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Christopher Wright wrote:
 Andrei has put up a few enhancement requests in the bugzilla:
 http://d.puremagic.com/issues/show_bug.cgi?id=2784
 http://d.puremagic.com/issues/show_bug.cgi?id=2785
 http://d.puremagic.com/issues/show_bug.cgi?id=2786
Yah, this too: http://d.puremagic.com/issues/show_bug.cgi?id=2050
 These are intended to change interfaces from being solely a tool of  
 polymorphism into a way of specifying type constraints. The additions  
 recommended can only be used at compile time (constructors, static  
 functions, and nested types).
Yah. Let me add that I haven't thought the changes through, but I posted them to foster discussion, which is happening (thanks!).
 I grant that it would be quicker and clearer to write:
 interface Foo
 {
    static void stuff();
    this (int);
 }
 template Template(Arg : Foo) {}
  than to write:
 template Template(Arg) if (is (typeof (new Arg(0)) &&  
 isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many of us can instantly figure how the former works, whereas the latter is thoroughly obscure. Let me also pull the definition of a couple of range types in std.range (by the way, I should commit the new Phobos today): template isInputRange(R) { enum bool isInputRange = is(typeof( { R r; // can define a range object if (r.empty) {} // can test for empty r.next; // can invoke next auto h = r.head; // can get the head of the range }())); } I wrote it as clearly as I could, and it doesn't quite look that pretty. I didn't even know the typeof({ ... }()) trick is possible; I saw it somewhere on this group, and took to it. Otherwise the code would have been even more convoluted (along the lines of what you wrote, just more of it). Furthermore, if a type is not a range, there's no simple way to output an error message telling exactly which test if failed. The only test possible is e.g. isInputRange!MyType. I think we can't quite be happy that this is D's offering with regard to concepts. On the other hand, we'd like to avoid the aggravation of C++ concepts, which, in my humble opinion, have a very low power/complexity ratio. So I wanted to look at how interfaces can be reasonably extended into expressing concepts while still being strongly integrated with their classic runtime polymorphic role.
 However, I'm not sure whether this would be used much at all, and it  
 deserves some discussion.

 interface Foo
 {
     extern void bar(int, Foo, double);
 }
  meaning that a non-member function bar should exist that accepts an  
 int, *the implementor of Foo*, and a double.
  This is a huge and silent divergence from the standard meaning of  
 using the interface name; it would allow:
 class C : Foo
 {
     static void bar(int, C, double);
 }
  and disallow:
 class C : Foo
 {
     static void bar(int, Foo, double);
 }
  Thoughts? Any concerns that I have not raised? I don't do sufficient  
 metaprogramming to find any of this useful, I admit.
I thought of that, too. One option is to parameterize Foo with its subtype's name: interface Foo(X) { extern void bar(int, X, double); } Then you'd require C : Foo!C and so on. I'm not sure how important this detail is, but it is worth thinking of. Another issue is that constructors in a struct are one thing, whereas in a class they are quite a different thing (references of a class can be copied!) Andrei
I'm not sure I understand everything you intend so lets clear things a little. I agree there should be a way to enforce struct to implement some.. contract. But I believe you took a wrong way by using pseudo-interface inheritance. First of all, it's called Concept in C++0x. I suggest to use the same name in D, too. (Yes, that's one more keyword, but this is just a discussion, right, and you didn't listen all my arguments yet). concept Range(T) { bool empty; T value; void next(); } I don't think "void next;" is okay, besides, it's always a function anyway! On the other side, I can image an infinite range that returns constant values and next is a do nothing function, but still you can't have a member of type void. Concept is different from interface. Concept says that if typeof(r) satisfies a Range concept, then the following syntax is allowed: bool e = r.empty; T v = r.value; r.next(); But it doesn't say "how". r.empty may be a property, a (static) member, or even an enum. And that's exactly what's needed for Range definition! On the contrary, interface defines a set of *virtual functions* that are invokable through an instance of that interface. That's why I don't support an idea of the following: interface Foo { this(int i); typedef Bar; } Foo foo = new Foo(42); // huh? Foo.Bar x; //what's x.typeof? BTW, why is(typeof(x)) is alowed but typeof(x) is not? I quite don't like x.typeof Surely, you'll disallow both syntaxes, but this gets messy. Some of functions are callable through interface and some are only callable through a class that implements that interface! Once again, I state that you you mistakenly mix two different concepts (pun is not inteded). concept Foo { int(int i); typedef Bar; // fine } Second, I believe structs *can* safely implement interfaces (hello, Weed!). They still shouldn't support inheritance, but *interface* inheritance: interface Foo { int bar(); } struct FooImpl : Foo { int bar() { return 42; } } int acceptsFoo(Foo f) { return f.bar(); } FooImpl fooImpl; acceptsFoo(fooImpl); // yes! They'll get an implicit vtbl ptr, and since they don't support struct inheritance, no slicing is possible.
Apr 04 2009
next sibling parent Kagamin <spam here.lot> writes:
Denis Koroskin Wrote:

 interface Foo
 {
     this(int i);
     typedef Bar;
 }
 
 Foo foo = new Foo(42); // huh?
 Foo.Bar x; //what's x.typeof?
I think, template will accept type T:Foo that satisfies concept Foo and T foo=new T(42); T.Bar x;
Apr 04 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 I'm not sure I understand everything you intend so lets clear things a 
 little.
 
 I agree there should be a way to enforce struct to implement some.. 
 contract.
 But I believe you took a wrong way by using pseudo-interface inheritance.
 
 First of all, it's called Concept in C++0x. I suggest to use the same 
 name in D, too. (Yes, that's one more keyword, but this is just a 
 discussion, right, and you didn't listen all my arguments yet).
Makes sense.
 concept Range(T)
 {
    bool empty;
    T value;
    void next();
 }
 
 I don't think "void next;" is okay, besides, it's always a function 
 anyway! On the other side, I can image an infinite range that returns 
 constant values and next is a do nothing function, but still you can't 
 have a member of type void.
So far so good.
 Concept is different from interface. Concept says that if typeof(r) 
 satisfies a Range concept, then the following syntax is allowed:
 
 bool e = r.empty;
 T v = r.value;
 r.next();
 
 But it doesn't say "how". r.empty may be a property, a (static) member, 
 or even an enum. And that's exactly what's needed for Range definition!
Yah, but let me point out that interfaces can be also relaxed to require less conformance, just like you describe.
 On the contrary, interface defines a set of *virtual functions* that are 
 invokable through an instance of that interface.
It does so currently. It doesn't mean the definition can't be improved, no?
 That's why I don't 
 support an idea of the following:
 
 interface Foo
 {
    this(int i);
    typedef Bar;
 }
 
 Foo foo = new Foo(42); // huh?
 Foo.Bar x; //what's x.typeof?
 
 BTW, why is(typeof(x)) is alowed but typeof(x) is not? I quite don't 
 like x.typeof
 
 Surely, you'll disallow both syntaxes, but this gets messy. Some of 
 functions are callable through interface and some are only callable 
 through a class that implements that interface!
 Once again, I state that you you mistakenly mix two different concepts 
 (pun is not inteded).
I think this is really funny reading: http://www.thebestpageintheuniverse.net/c.cgi?u=puns It convinced me to avoid emphasizing or denying my puns :o). Anyway, I agree with your point that uses of interface as concept may sometimes interfere with its uses in the traditional sense. One thing that comes to mind is: interface Interface { void foo(); } void foo(T : Interface)() { ... } class C { void foo(); } C does not explicitly declare abiding to Interface. However, structurally it does. Should foo be called? If interface is meant for binary binding, no. If interface is meant for concept checking, maybe. (The notion of "auto concept" in C++ is akin to this. There is currently a discussion on the C++ standardization mailing list on whether most concepts should be "auto" or not.)
 concept Foo
 {
    int(int i);
    typedef Bar; // fine
 }
 
 Second, I believe structs *can* safely implement interfaces (hello, 
 Weed!). They still shouldn't support inheritance, but *interface* 
 inheritance:
 
 interface Foo
 {
    int bar();
 }
 
 struct FooImpl : Foo
 {
    int bar()
    {
        return 42;
    }
 }
 
 int acceptsFoo(Foo f)
 {
    return f.bar();
 }
 
 FooImpl fooImpl;
 acceptsFoo(fooImpl); // yes!
 
 They'll get an implicit vtbl ptr, and since they don't support struct 
 inheritance, no slicing is possible.
 
I don't see enough good uses for this feature. Andrei
Apr 04 2009
prev sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
On 04/04/2009 17:41, Denis Koroskin wrote:
 I'm not sure I understand everything you intend so lets clear things a
 little.

 I agree there should be a way to enforce struct to implement some..
 contract.
 But I believe you took a wrong way by using pseudo-interface inheritance.

 First of all, it's called Concept in C++0x. I suggest to use the same
 name in D, too. (Yes, that's one more keyword, but this is just a
 discussion, right, and you didn't listen all my arguments yet).

 concept Range(T)
 {
 bool empty;
 T value;
 void next();
 }

 I don't think "void next;" is okay, besides, it's always a function
 anyway! On the other side, I can image an infinite range that returns
 constant values and next is a do nothing function, but still you can't
 have a member of type void.

 Concept is different from interface. Concept says that if typeof(r)
 satisfies a Range concept, then the following syntax is allowed:

 bool e = r.empty;
 T v = r.value;
 r.next();

 But it doesn't say "how". r.empty may be a property, a (static) member,
 or even an enum. And that's exactly what's needed for Range definition!

 On the contrary, interface defines a set of *virtual functions* that are
 invokable through an instance of that interface. That's why I don't
 support an idea of the following:

 interface Foo
 {
 this(int i);
 typedef Bar;
 }

 Foo foo = new Foo(42); // huh?
 Foo.Bar x; //what's x.typeof?

 BTW, why is(typeof(x)) is alowed but typeof(x) is not? I quite don't
 like x.typeof

 Surely, you'll disallow both syntaxes, but this gets messy. Some of
 functions are callable through interface and some are only callable
 through a class that implements that interface!
 Once again, I state that you you mistakenly mix two different concepts
 (pun is not inteded).

 concept Foo
 {
 int(int i);
 typedef Bar; // fine
 }

 Second, I believe structs *can* safely implement interfaces (hello,
 Weed!). They still shouldn't support inheritance, but *interface*
 inheritance:

 interface Foo
 {
 int bar();
 }

 struct FooImpl : Foo
 {
 int bar()
 {
 return 42;
 }
 }

 int acceptsFoo(Foo f)
 {
 return f.bar();
 }

 FooImpl fooImpl;
 acceptsFoo(fooImpl); // yes!

 They'll get an implicit vtbl ptr, and since they don't support struct
 inheritance, no slicing is possible.
What you define is Concets *in C++* and interface *in Java*. D doesn't have to use the same definitions. D interfaces can represent abstract types. for example, say we have this interface: interface I { this(int i); alias A; void funcA(); final void funcB(); } struct A : I {...} class B : I {...} why not make both A and B do exactly the same with I? meaning both inherit polymorphically funcA (it is in the virtual table for *both*) and statically at compile-time the compile time symbols like the alias A above. IMO, this is more consistent. as you said above, there's nothing to prevent polymorphic struct inheritance of interfaces since it doesn't introduce the slicing problem. regarding duct-typing: C++ needs this for compatibility with existing code. Why do you think that D needs to do the same choice? wouldn't it be more consistent if D would not provide two different semantics sets one for compile-time and one for run-time? D will provide things like Ranges as interfaces in the stdlib, and any type that supports this interface should specify that. from Andrei's post:
 interface Interface { void foo(); }
 void foo(T : Interface)() { ... }
 class C { void foo(); }

 C does not explicitly declare abiding to Interface. However, structurally it
does. Should foo be called? If interface is meant for binary binding, no. If
interface is meant for concept checking, maybe. (The notion of "auto concept"
in C++ is akin to this. There is currently a discussion on the C++
standardization mailing list on whether most concepts should be "auto" or not.)
in the above case, I think I prefer the binary binding option.
Apr 04 2009
parent reply Yigal Chripun <yigal100 gmail.com> writes:
Also, I don't understand why D needs a separate syntax for primitive types.
I don't like this whole "alias this" idea.
why can't we just use:

struct S : int { ... }

after all, that exactly what's that feature is trying to do, isn't it?
Apr 04 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Yigal Chripun:
 Also, I don't understand why D needs a separate syntax for primitive types.
Generally D can work some more in the direction of unifying primitive types and objects. Some of it can be done with no performance price to pay. Bye, bearophile
Apr 04 2009
parent reply grauzone <none example.net> writes:
bearophile wrote:
 Yigal Chripun:
 Also, I don't understand why D needs a separate syntax for primitive types.
Generally D can work some more in the direction of unifying primitive types and objects. Some of it can be done with no performance price to pay.
Like which?
 Bye,
 bearophile
Apr 04 2009
parent "Robert Jacques" <sandford jhu.edu> writes:
On Sat, 04 Apr 2009 15:38:03 -0400, grauzone <none example.net> wrote:
 bearophile wrote:
 Yigal Chripun:
 Also, I don't understand why D needs a separate syntax for primitive  
 types.
Generally D can work some more in the direction of unifying primitive types and objects. Some of it can be done with no performance price to pay.
Like which?
 Bye,
 bearophile
One example is fixed length arrays, which only generate a field for array length when converted to dynamic arrays. Similarly, structs with interfaces would not need a pointer to their vtable in the struct, it (the pointer, not the vtable) would be created when converted to an interface.
Apr 04 2009
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
2784: interface Foo { typedef Bar; }
- confused me for a while, so a clearer description might be nice
-- i.e. clarify that something like 'new I.bar()' is invalid.
- seems only to be useful as part of the other contract-like interface  
enhancements
-- Like 2786 & 2785 below, this creates a difference between normal  
interface members and typedefs, which I don't like.

2785: interface Foo{ extern void bar(int, Foo, double);
- I like the concept of extern functions in this concept, though it does  
rise questions of what scopes/modules are used for match searching.
- The use of Foo to mean the class name seems like the wrong keyword.
-- What if I truly wanted a function that took a Foo?
-- This makes these function definitions behave differently than  
definitions outside the interface. Perhaps 'typeof(this)'
- Like 2786 below, this creates a difference between normal interface  
members and externs, which I don't like.

2786: Interfaces should be able to require constructors
- Seems like a decent idea.
- But, this creates a difference between normal interface members and the  
constructor, which I don't like:
-- the implementors                    have a ___     // constructor
-- the implementors and the interface  have a ___     // everything else

2050: Interfaces with static/final methods with method bodies
- I like the idea of defining that an interface implementor should have  
static or final methods.
- However, there seem to be some major composability issues, with  
implementing two interfaces with identical final / static methods.
-- i.e. this is the classic diamond problem of multiple inheritance, just  
with functions instead of functions and data.
-- This also applies to overloading an interface's static or final method.  
Is it possible? What happens when the class is accessed through the  
interface?
- How is this superior to the current interface + mixin approach?
-- Or an mixin-able interface approach? i.e. mixin myInterface; // Add  
myInterface's method bodies to a class

Regarding Interfaces and Concepts
Though struct interfaces, etc would be very nice, couldn't compile time  
reflection be used to create a Duck/Concept-type template constraint:
template void foo(T)(T x, T y)
     if( isDuck!(T,InputRange) ) {...}

Summary
Essentially all these enhancements would create a major difference between  
an interface and its implementor, which I think is a Bad Idea(tm). And the  
problem its trying to solve (i.e. c++ Concepts) is probably better solved  
with a general compile-time reflection template, than by altering  
interfaces.
Apr 04 2009
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Christopher Wright Wrote:

 The idea is that the syntax 
 of template constraints is sufficiently obtuse that you need to use 
 idioms to get around it
So they should be fixed to become usable.
 Using that, it's difficult to determine what types you can pass to Template.
It's difficult only if AcceptableToTemplate is unreadable.
Apr 05 2009
prev sibling parent Kagamin <spam here.lot> writes:
Andrei Alexandrescu Wrote:

 interface Interface { void foo(); }
 void foo(T : Interface)() { ... }
 class C { void foo(); }
 
 C does not explicitly declare abiding to Interface. However, 
 structurally it does. Should foo be called? If interface is meant for 
 binary binding, no. If interface is meant for concept checking, maybe.
Interface[] rg; interface Interface { void foo(); } void foo(T : Interface)(T i) { rg~=i; } class C { void foo(); } What should happen here? Template will accept C and give error?
Apr 05 2009