d中类型对象实现元编程

原文
Hana启发.
如果想实现找出包含类型最大大小.在D中这很容易

import std.meta: AliasSeq;
import std.traits: Largest;
alias Types = AliasSeq!(int, float, char, double);
enum maxSize = Largest!(Types).sizeof;
writeln(maxSize);//8 bytes

Largest实现不好看(递归),.不用模板来计算类型.用普通函数,创建类型对象:

import std.traits: isInstanceOf;
enum isType(T) = isInstanceOf!(Type, T);
struct Type(T){
    alias type = T;
    string toString()
    {
        return "Type!("~T.stringof~")";
    }
}
enum t  = Type!(int)();
enum t1 = Type!(string)();

这样,按普通对象一样使用类型,如下判断类型是否相同:

enum equals(A,B)(Type!A, Type!B){
    return is(A == B);
}
enum t  = Type!(int)();
enum t1 = Type!(string)();

writeln(t.equals(t1)); // false
writeln(equals(t, t1)); // false
writeln(equals(Type!int(), Type!int())); // true

创建TypeTuple来容纳多个类型.

enum isTypeTuple(T) = isInstanceOf!(TypeTuple, T);

struct TypeTuple(Types...){
    import std.meta: allSatisfy;
    static assert(allSatisfy!(isType, Types), "可变参,要求是`类型`类型");
    Types expand;
    alias expand this;
    string toString()
    {
        import std.range;
        string[] s;
        foreach(t; expand){
            s~= t.toString();
        }
        return "TypeTuple!(" ~ s.join(", ") ~")";
    }
}
enum typeTuple(Types...)(Types){
    return TypeTuple!Types();
}

顺便,用toString打印生成类型,避免伪码.

enum types = TypeTuple!(Type!int, Type!char, Type!float, Type!double)();
//or
enum types = typeTuple(Type!int, Type!char, Type!float, Type!double);

辅助函数:

enum tupleFromTypes(Ts...)(){//类型元组.
    import std.meta: staticMap;
    return TypeTuple!(staticMap!(Type, Ts))();
}
enum types = tupleFromTypes!(int,double, int,float);

实现元函数:

//过滤
enum filter(alias f, Tup)(Tup){
    static assert(isTypeTuple!(Tup), tup.stringof~" 不是类型元组.");
    enum tup = Tup();
    static if(tup.length == 0){
        return typeTuple();
    }
    else static if(f(tup[0])){
        return typeTuple(tup[0], filter!(f)(typeTuple(tup[1..$])).expand);
    }
    else{
        return filter!(f)(typeTuple(tup[1..$]));
    }
}
//使用
enum types = tupleFromTypes!(int, double, string, float);
enum biggerThan4 = filter!(t => t.type.sizeof > 4)(types);
writeln(biggerThan4);// TypeTuple!(Type!(double), Type!(string))
//映射
enum map(alias f, Tup)(Tup){
    static assert(isTypeTuple!(Tup), tup.stringof~" is not a TypeTuple.");
    enum tup = Tup();
    static if(tup.length == 0){
        return typeTuple!();
    }
    else{
        return typeTuple(f(tup[0]), map!(f)(typeTuple(tup[1..$])).expand);
    }
}
enum types = tupleFromTypes!(int, double, string, float);
enum onlyInts = map!(t => Type!int())(types);
writeln(onlyInts);// TypeTuple!(Type!(int), Type!(int), Type!(int), Type!(int))
//
enum types = tupleFromTypes!(int, double, string, float);
enum smallerThan5 = map!((t){
    static if(t.type.sizeof > 4){
        return Type!int();
    }
    else{
        return t;
    }
})(types);// TypeTuple!(Type!(int), Type!(int), Type!(int), Type!(float))
writeln(smallerThan5);

要在编译时运行,请用静如.

enum indexOf(T,Tup)(T, Tup){
    static assert(isTypeTuple!(Tup), tup.stringof~" is not a TypeTuple.");
    static assert(isType!(T), T.stringof~" is not a Type.");
    enum t = T();
    enum tup = Tup();
    foreach(index, type; tup.expand){
        if(type.equals(t)){
            return index;
        }
    }
    return -1;
}
enum types = tupleFromTypes!(int, double, string, float);
enum index = indexOf(Type!string(), types);
writeln(index);// 2
//快排
enum partition(alias f, Tup)(Tup){//分区
    enum tup = Tup();
    return partitionImpl!(f)(tup, typeTuple(), typeTuple());
}

enum partitionImpl(alias f, Tup, TupLeft, TupRight)(Tup, TupLeft, TupRight){
    import std.typecons: tuple;
    enum tup = Tup();
    enum l = TupLeft();
    enum r = TupRight();

    static if(tup.length == 0){
        return tuple(l, r);
    }
    else{
        static if(f(tup[0])){
            return partitionImpl!(f)(typeTuple(tup[1..$]), typeTuple(tup[0], l.expand), typeTuple(r.expand));
        }
        else{
            return partitionImpl!(f)(typeTuple(tup[1..$]), typeTuple(l.expand), typeTuple(tup[0], r.expand));
        }

    }
}

enum sort(alias f,Tup)(Tup){
    enum tup = Tup();
    static if(tup.length == 0){
        return typeTuple();
    }
    else static if(tup.length == 1){
        return typeTuple(tup[0]);
    }
    else{
        enum middle= tup[0];
        enum t = partition!(t => f(t, middle))(typeTuple(tup[1..$]));
        enum left = t[0];
        enum right = t[1];
        return typeTuple(left.expand, middle, right.expand);
    }
}
//使用
enum types = tupleFromTypes!(int, double, string, float);
enum sortedTypes = sort!((t1, t2) => t1.type.sizeof > t2.type.sizeof)(types);
writeln(sortedTypes);// TypeTuple!(Type!(string), Type!(double), Type!(int), Type!(float))
//最大尺寸
enum types = tupleFromTypes!(int, double, string, float);
enum sortedTypes = sort!((t1, t2) => t1.type.sizeof > t2.type.sizeof)(types);
enum maxSize = sortedTypes[0].sizeof;
writeln(maxSize);// 8字节

类型对象使元编程就像使用普通函数.

posted @   zjh6  阅读(21)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示