bearophile: >To write some templates as compile-time functions you may need to add a new >type to D, named "type":<
To see if the idea of compile-time functions that process compile-time variables of type "type" isn't fully crazy I have translated some of the D1 templates of my dlibs into such compile-time functions. The following code shows a template and its possible translation. The code is of course untested and there can be many mistakes of mine. // ------------------------------- private template AA_impl(KeyType, ValueType) { ValueType[KeyType] result; const ValueType[KeyType] res = result; } template AA(KeyType, ValueType) { const ValueType[KeyType] AA = AA_impl!(KeyType, ValueType).res; } TyVal[TyKey] newaa(type TyKey, type TyVal) { TyVal[TyKey] aa; return aa; } // ------------------------------- template AAKeyType(T) { alias typeof(T.keys[0]) AAKeyType; } template AAValType(T) { alias typeof(T.values[0]) AAValType; } type aaKeyType(TV, TK)(TV[TK] aa) { return TK; } type aaValType(TV, TK)(TV[TK] aa) { return TV; } type aaKeyType(TV, TK)(type TV[TK]) { return TK; } type aaValType(TV, TK)(type TV[TK]) { return TV; } // ------------------------------- template ALL(alias Predicate, Types...) { static if (Types.length == 0) const bool ALL = true; else const bool ALL = Predicate!(Types[0]) && ALL!(Predicate, Types[1 .. $]); } bool All(alias pred, type[] types...) { static foreach (T; types) static if (!pred(T)) return false; return true; } ANY/Any are similar. // ------------------------------- template BaseTypedef(T) { static if( is( T BaseType1 == typedef ) ) alias BaseTypedef!(BaseType1) BaseTypedef; else alias T BaseTypedef; } type baseTypedef(type T) { // the syntax of is() may be improved in many ways static while ( is( T BaseType1 == typedef ) ) T = BaseType1; return T; } A problem of the "static foreach" (that Walter will face) is that templates are functional, so their values are immutable. And Scheme shows that in a language with no mutability it's not much useful to have for/foreach loops. In that "static while" loop the variable T of type type, is a mutable. // ------------------------------- template CastableTypes(Types...) { static if (Types.length <= 1) const CastableTypes = true; else const CastableTypes = is(typeof(Types[0] == Types[1])) && CastableTypes!(Types[1 .. $]); } bool areCastableTypes(type[] Types)(type... types) { static foreach (T; types[1 .. $]) static if (!is(typeof(Types[0] == Types[1]))) return false; return true; } // ------------------------------- template DeconstArrayType(T) { static if (IsStaticArray!(T)) alias typeof(T[0])[] DeconstArrayType; else alias T DeconstArrayType; } (DeconstArrayType works if T isn't a static array, this is very useful in my code) type deconstArrayType(type T) { static if (isStaticArray!(T)) return typeof(T[0])[]; //return (T[0]).typeof[]; else return T; } // ------------------------------- template IsType(T, Types...) { // Original idea by Burton Radons, modified static if (Types.length == 0) const bool IsType = false; else const bool IsType = is(T == Types[0]) || IsType!(T, Types[1 .. $]); } bool isType(T, type[] types...) { static foreach (TX; types) // now == works among run-time variables of type "type". static if (T == TX) return true; return false; } Or even simpler, if the compiler understands that isType is a compile-time-function-only: bool isType(T, type[] types...) { foreach (TX; types) if (T == TX) return true; return false; } With Any() and a compile-time lambda you can write: bool isType(T, type[] types...) { return Any((type TX){ return T == TX; }, types); } :-) // ------------------------------- Bye, bearophile