Output a proper error message when using hasType with an invalid type. Fixes #1.

This commit is contained in:
Sönke Ludwig 2015-08-27 11:27:57 +02:00
parent 84d6c8da80
commit 96f18356f7

View file

@ -175,26 +175,6 @@ struct TaggedAlgebraic(U) if (is(U == union) || is(U == struct))
private @trusted @property ref inout(T) trustedGet(T)() inout { return *cast(inout(T)*)m_data.ptr; }
}
bool hasType(T, U)(in ref TaggedAlgebraic!U ta)
{
switch (ta.kind) {
default: return false;
foreach (i, FT; ta.FieldTypes)
static if (is(FT == T)) {
case __traits(getMember, ta.Kind, ta.fieldNames[i]):
return true;
}
}
assert(false); // never reached
}
ref inout(T) get(T, U)(ref inout(TaggedAlgebraic!U) ta)
{
assert(hasType!(T, U)(ta));
return ta.trustedGet!T;
}
/** Operators and methods of the contained type can be used transparently.
*/
@safe unittest {
@ -465,6 +445,60 @@ unittest {
assert(c[0] == "hello");
}
/** Tests if the algebraic type stores a value of a certain data type.
*/
bool hasType(T, U)(in ref TaggedAlgebraic!U ta)
{
alias Fields = Filter!(fieldMatchesType!(U, T), ta.fieldNames);
static assert(Fields.length > 0, "Type "~T.stringof~" cannot be stored in a "~(TaggedAlgebraic!U).stringof~".");
switch (ta.kind) {
default: return false;
foreach (i, fname; Fields)
case __traits(getMember, ta.Kind, fname):
return true;
}
assert(false); // never reached
}
///
unittest {
union Fields {
int number;
string text;
}
TaggedAlgebraic!Fields ta = "test";
assert(ta.hasType!string);
assert(!ta.hasType!int);
ta = 42;
assert(ta.hasType!int);
assert(!ta.hasType!string);
}
unittest { // issue #1
union U {
int a;
int b;
}
alias TA = TaggedAlgebraic!U;
TA ta = TA(0, TA.Kind.b);
static assert(!is(typeof(ta.hasType!double)));
assert(ta.hasType!int);
}
/** Gets the value stored in an algebraic type based on its data type.
*/
ref inout(T) get(T, U)(ref inout(TaggedAlgebraic!U) ta)
{
assert(hasType!(T, U)(ta));
return ta.trustedGet!T;
}
/// Convenience type that can be used for union fields that have no value (`void` is not allowed).
struct Void {}
@ -894,6 +928,11 @@ private template isMatchingUniqueType(U) {
}
}
private template fieldMatchesType(U, T)
{
enum fieldMatchesType(string field) = is(typeof(__traits(getMember, U, field)) == T);
}
private template FieldTypeOf(U) {
template FieldTypeOf(string name) {
alias FieldTypeOf = typeof(__traits(getMember, U, name));