Composition with mixin and templates

I can make up a structure ABthat has all the members of the structures Aand B:

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;

But how can I build ABif I do not have control over Aand B, and I do not have AFieldsand BFields? That is, how to write a template CatStructto compile the following code?

struct A { int a; }
struct B { int b; }
mixin CatStruct!("AB", A, B);
AB ab;
ab.a = 1; ab.b = 2;
+4
source share
3 answers

There is plenty of room for coverage (members, functions, templates, etc.). However, here is an idea to get you started:

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);
}

, , , ( Proxy, , ).

, -, (aProxy, bProxy), opDispatch , , .

+6

, , , :

http://dlang.org/phobos/std_traits.html#Fields

, . CatStruct . :

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) 
                 // this line is a monster, see the end of this answer
                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()); 
} 

mix mixin... mixins , . , , , .

, , , , , opDispatch, ( , , ).

, , . mixin - mixin, . . , , .

FieldTypeTuple FieldNameTuple stdlib, , , , .

, , , , . ( alias this, -.)


, , , , code ~=, . code ~= field.stringof ~ " "~ FieldNameTuple!t[idx] ~ ";";

tl; dr: , , , mixin() . /

. - FieldTypeTuple, field.stringof - .

, struct A - .

// using my color.d just cuz I have it easily available
// but it could be anything, so don't worry about downloading it
struct A { import arsd.color; Color a; } 

AB ab; 
import arsd.color; 
ab.a = Color.white; ab.b = 2;  // we expect this work, should be the same type

struct A, mixin.

mixin,

                // comment fancy line
               // code ~= "std.traits.FieldTypeTuple!(T["~std.conv.to!string(oidx)~"])["~std.conv.to!string(idx)~"] "~ std.traits.FieldNameTuple!t[idx] ~ ";"; 

               // paste in simple line
                code ~= field.stringof ~ " "~ std.traits.FieldNameTuple!t[idx] ~ ";";

:

$ dmd f.d ~/arsd/color.d
f.d-mixin-31(31): Error: undefined identifier 'Color' 
f.d(4): Error: mixin f.CatStruct!("AB", A, B) error instantiating 

Zoinks! , "". - Color , .... :

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; 

:

$ dmd f.d ~/arsd/color.d
f.d(12): Error: cannot implicitly convert expression (white()) of type Color to Color

: , - - , " ", : .

, , , .

FieldTypeTuple, , , . , , .

, , , , , , . - , !:) , , , -.

+9

, , :

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

// helper template to interleave 2 alias lists
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;
}

// helper template to produce tuple template parameters
template FieldTypeNameTuple(A)
{
    alias Interleave!(Fields!A, FieldNameTuple!A) FieldTypeNameTuple;
}

template CatStruct(A...)
{
    alias Tuple!(staticMap!(FieldTypeNameTuple, A)) CatStruct;
}

// usage

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

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

Source: https://habr.com/ru/post/1607702/


All Articles