Constraints & Concepts [Was: Re: C++0x news]
bearophile
bearophileHUGS at lycos.com
Mon Mar 15 09:30:57 PDT 2010
Walter Bright:
> Here's a comparison I did of C++0x proposed features and D a while back.
> It's out of date and incomplete, but it's a reasonable overview:
> http://www.digitalmars.com/d/2.0/cpp0x.html
> I suppose I need to revisit it now that C++0x is nearing completion.
In the past I didn't understand the section about Concepts of that page , now I am understanding most of it, thanks to this very nice article that explains the semantics and usefulness of concept maps:
http://www.devx.com/SpecialReports/Article/38864/1954?pf=true
This article has let me understand why concept maps are much more powerful (and probably more useful) than D template Constraints.
General comment on the cpp0x.html page: C++/C++0x and Java are legacy languages (but the most successful), so they can't be enough to design D. So I suggest to try for few days the C#3.5+ and Scala languages too, they probably already solve some of the problems that need to be found D still...
Specific comments on that cpp0x.html page:
>Concept maps: No (but could be done with proxy objects)<
I don't fully understand, I'd like to see a small example of this (it can be added to that page too).
>Axioms: Yes (as static asserts and function preconditions)<
This is a (too much) common example of axiom from Wikipedia:
http://en.wikipedia.org/wiki/Concepts_%28C%2B%2B%29#Axioms
concept Semigroup< typename Op, typename T> : CopyConstructible<T> {
T operator()(Op, T, T);
axiom Associativity(Op op, T x, T y, T z) {
op(x, op(y, z)) == op(op(x, y), z);
}
}
Function precoditions are currently used at run-time (a sufficiently smart compiler can use some of them at compile time, but it's not easy). And static asserts don't help a lot here.
>All operations on constrained types must be specified in concept/constraint: No<
After reading that article on devx.com I think this can be a nice feature to have in D too, because some times the lack of semantic analysis on uninstantiated D templates unnerves me a little (while I think the other two features like concept maps inheritance and the adaptors inside concept maps are less important). But I am not sure how it can be implemented. If someone has ideas I'd like to know them.
In D a template Constraints can contain the methods that must exist, as in a C++0x Concept, I think this is the way to express it, using the methods inside a __traits(compiles):
import std.stdio: writeln;
template IsPolygon(P) { // like a Concept
enum bool IsPolygon = __traits(compiles, { int x = num_sides(P());
auto d = side_len(P(), 0);
typeof(d) r = 0;
r += d;
});
}
typeof(P.sides[0]) perimeter(P)(const ref P poly) if (IsPolygon!P) {
typeof(return) sum = 0;
foreach (i; 0 .. num_sides(poly))
sum += side_len(poly, i);
return sum;
}
// class Int { // problem!
struct Int {
int x;
void opOpAssign(string Op:"+=")(Int other) { this.x += other.x; }
static Int opCall(int value) { Int i; i.x = value; return i; }
}
struct Triangle { Int[3] sides; }
int num_sides(const ref Triangle tri) { return Triangle.sides.length; }
typeof(Triangle.sides[0]) side_len(const ref Triangle tri, int index) { return tri.sides[index]; }
static assert(IsPolygon!Triangle); // this makes sure Triangle is a polygon
void main() {
Triangle t = Triangle([Int(10), Int(20), Int(30)]);
auto p = perimeter(t);
writeln(typeid(typeof(p)), " ", p);
}
There's no good way to let templates detect an operator missing in the concept, like explained in that article.
A possible syntax can be to modify this:
typeof(P.sides[0]) perimeter(P)(const ref P poly) if (IsPolygon!P) {
Into a syntax that asks the compiler to perform the semantic tests even on the uninstantiated template. Maybe something like:
typeof(P.sides[0]) perimeter(P)(const ref P poly) if (__traits(satisfiesConcept, perimeter, IsPolygon)) {
Bye,
bearophile
More information about the Digitalmars-d
mailing list