public import std.algorithm;
public import std.array;
public import std.conv;
public import std.range;
public import std.stdio;
public import std.string;
public import std.typecons;

template DeriveCreate()
{
	this(TS...)(TS params)
	{
		this.tupleof = params;
	}
}

template DeriveCompare()
{
override:
	bool opEquals(Object rhs)
	{
		return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupleof);
	}

	int opCmp(Object rhs)
	{
		return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).tupleof));
	}

	hash_t toHash()
	{
		hash_t v = 0;
		foreach(mem; this.tupleof) {
			v *= 11;
			static if(__traits(compiles, v^=mem))
				v ^= mem;
			else
				v ^= typeid(mem).getHash(&mem);
		}
		return v;
	}
}

template DeriveShow()
{
override:
	string toString()
	{
		string str = text(typeof(this).stringof, "(");
		foreach(i,mem; this.tupleof) {
			if(i) str ~= ", ";
			str = text(str, this.tupleof[i].stringof[5..$], ":",  mem);
		}
		return str ~ ")";
	}
}
