module runnable;
import std.stdio;
bool deeplyEqual(T)(auto ref T value1, auto ref T value2)
{
static if (is(T==struct) || is(T==class))
{
foreach(member; __traits(allMembers, T))
{
enum getMember1 = "__traits(getMember, value1, member)";
enum getMember2 = "__traits(getMember, value2, member)";
alias MT = typeof(mixin(getMember1));
static if (is(MT==struct) || is(MT==class) && MT.tupleof.length)
{
if (!deeplyEqual(mixin(getMember1), mixin(getMember2)))
return false;
}
else if (mixin(getMember1) != mixin(getMember2))
return false;
}
return true;
}
else return value1 == value2;
}
struct Foo{uint a; int b;}
struct Bar{float c = 0; Foo foo;}
void main()
{
Bar x, y;
writeln(deeplyEqual(x, y));
x.foo.b = 8;
writeln(deeplyEqual(x, y));
}
bW9kdWxlIHJ1bm5hYmxlOwppbXBvcnQgc3RkLnN0ZGlvOwoKYm9vbCBkZWVwbHlFcXVhbChUKShhdXRvIHJlZiBUIHZhbHVlMSwgYXV0byByZWYgVCB2YWx1ZTIpCnsKICAgIHN0YXRpYyBpZiAoaXMoVD09c3RydWN0KSB8fCBpcyhUPT1jbGFzcykpCiAgICB7CiAgICAgICAgZm9yZWFjaChtZW1iZXI7IF9fdHJhaXRzKGFsbE1lbWJlcnMsIFQpKQogICAgICAgIHsKICAgICAgICAgICAgZW51bSBnZXRNZW1iZXIxID0gIl9fdHJhaXRzKGdldE1lbWJlciwgdmFsdWUxLCBtZW1iZXIpIjsKICAgICAgICAgICAgZW51bSBnZXRNZW1iZXIyID0gIl9fdHJhaXRzKGdldE1lbWJlciwgdmFsdWUyLCBtZW1iZXIpIjsKICAgICAgICAgICAgYWxpYXMgTVQgPSB0eXBlb2YobWl4aW4oZ2V0TWVtYmVyMSkpOwogICAgICAgICAgICBzdGF0aWMgaWYgKGlzKE1UPT1zdHJ1Y3QpIHx8IGlzKE1UPT1jbGFzcykgJiYgTVQudHVwbGVvZi5sZW5ndGgpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmICghZGVlcGx5RXF1YWwobWl4aW4oZ2V0TWVtYmVyMSksIG1peGluKGdldE1lbWJlcjIpKSkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAobWl4aW4oZ2V0TWVtYmVyMSkgIT0gbWl4aW4oZ2V0TWVtYmVyMikpCiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZWxzZSByZXR1cm4gdmFsdWUxID09IHZhbHVlMjsKfQoKc3RydWN0IEZvb3t1aW50IGE7IGludCBiO30Kc3RydWN0IEJhcntmbG9hdCBjID0gMDsgRm9vIGZvbzt9Cgp2b2lkIG1haW4oKQp7CiAgICBCYXIgeCwgeTsKICAgIHdyaXRlbG4oZGVlcGx5RXF1YWwoeCwgeSkpOwogICAgeC5mb28uYiA9IDg7CiAgICB3cml0ZWxuKGRlZXBseUVxdWFsKHgsIHkpKTsKfQA=