d组合结构

原文
题目:

template AFields() {int a;}
struct A { mixin AFields; }
template BFields() {int b;}
struct B { mixin BFields; }
struct AB { mixin AFields; mixin BFields; }
A a; a.a = 1;
B b; b.b = 2;
AB ab; ab.a = 3; ab.b = 4;

如何编写连接构,来编译.这里不控制A与B,也没有AFields/BFields.

struct A { int a; }
struct B { int b; }
mixin CatStruct!("AB", A, B);//这里.
AB ab;
ab.a = 1; ab.b = 2;

1命名元组

import std.meta, std.traits, std.typecons;

// 交织
template Interleave(A...)
{
    static if(A.length == 0)
        alias A Interleave;
    else
        alias AliasSeq!(A[0], A[A.length/2],
            Interleave!(A[1..A.length/2], A[A.length/2+1..$])) Interleave;
}

// 帮助函数
template FieldTypeNameTuple(A)
{
    alias Interleave!(Fields!A, FieldNameTuple!A) FieldTypeNameTuple;
}

template CatStruct(A...)
{
    alias Tuple!(staticMap!(FieldTypeNameTuple, A)) CatStruct;//静映射
}

// 用法

struct A { int a; }
struct B { int b; }
struct C { int c; }

alias CatStruct!(A, B, C) ABC;

使用代理

import std.typecons;

struct A { int a; }
struct B { int b; }

struct AB
{
  mixin MultiProxy!(A, B);
}

mixin template MultiProxy(A, B) {
  private A _a;
  private B _b;

  mixin Proxy!_a aProxy;
  mixin Proxy!_b bProxy;

  template opDispatch(string op) {
    static if (is(typeof(aProxy.opDispatch!op))) {
      alias opDispatch = aProxy.opDispatch!op;
    }
    else {
      alias opDispatch = bProxy.opDispatch!op;
    }
  }
}

unittest
{
  AB ab;
  ab.a = 4;
  ab.b = 5;

  assert(ab.a == 4);
  assert(ab.b == 5);
}

标准库方法

参考

mixin template CatStruct(string name, T...) { 
//连接构
    static import std.traits, std.conv; 
    private string _code_generator() { 
        string code = "struct " ~ name ~ " {"; 
        foreach(oidx, t; T) { 
            foreach(idx, field; std.traits.FieldTypeTuple!t) 
                 // 怪物行.
                code ~= "std.traits.FieldTypeTuple!(T["~std.conv.to!string(oidx)~"])["~std.conv.to!string(idx)~"] "~ std.traits.FieldNameTuple!t[idx] ~ ";"; 
        } 
        code ~= "}"; 
        return code; 
    } 
    mixin(_code_generator()); 
}

使用FieldTypeTupleFieldNameTuple,真正的模板插件,有简单的解决方法:命名mixin 模板,可消除歧义.
插件代码中使用了静态导入和全限定名,包括使用FieldTypeTuple的本地符号而不是field.stringof来尽量保持命名空间整洁.

struct A { import arsd.color; Color a; } 

AB ab; 
import arsd.color; 
ab.a = Color.white; ab.b = 2;
//接着
struct A { import arsd.color; Color a; } 
struct B { int b; } 
struct Color { static Color white() { return Color.init; } } 
mixin CatStruct!("AB", A, B);  

AB ab; 
import arsd.color; 
ab.a = Color.white; ab.b = 2;

对于与本地静态导入一起使用的长格式FieldTypeTuple,它始终指传入的实际类型.间接地,当然,但也很明确.

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