-
-
Notifications
You must be signed in to change notification settings - Fork 741
new std.traits templates: isSame, isSameTypleTuple, GetTemplateParent, GetTemplateArguments, isTemplateInstantiation #1367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
struct A{} | ||
} | ||
struct A4(alias fun,T...){} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is a good moment to gather all dummy types used by std.traits unit tests in one block and use unified naming for them, for maintenance reasons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok will fix
It is welcome addition (have totally forgot about templates when writing fullyQualifiedName for types >_<), but utility templates need to be much better defined and have strict constraints. By the way, while you are still on this, do you have any ideas about http://d.puremagic.com/issues/show_bug.cgi?id=10190 ? I still can't think any good workaround that does not involve patching DMD. Regarding functions, it is complicated because for aggregates symbol is also the type at the same time. Amd for functions plain symbol is not a type but parens-less call. I have no idea how to get function type without loosing function symbol (FunctionTypeOf will return type with all "T"'s instantiated). |
I'm arguing there's a good use case for isSame / isSameTypeTuple to work on 'everything', as i did. For restricted cases, ppl can use __traits(isSame), is(a==b), a==b depending on conditions. can you think of a way to get rid of the "N" parameters in isSameTypeTuple ? If so i can even fold isSameTypeTuple into isSame.
Yes, i have a fix for 10190 (i had submitted that bug actually:) ). Will make pull request after this is accepted. It depends on functionality in this pull.
also have a fix for functions. But not templated functions yet ! |
By the way, you commits don't seem to have a commit message. Will return to this later in the evening. |
can i amend commit messages from github? also, just found out that there exists a private template std.typetuple.isSame that seems to be equivalent to my proposed std.traits.isSame. So that proves that it was useful indeed! EDIT: added AliasTuple and removed isSameTypleTuple, which isn't necessary anymore. |
Change the pick in the beginning of a line to "r", then you can edit the commit messages and also squash them together into one big commit.
|
…TypeTuple since tuples can now be compared after wrapping through AliasTuple
made some improvements: |
There's a lot that needs fixing here, I'll review shortly. |
--- | ||
+/ | ||
template AliasTuple(T...){ | ||
alias AliasTuple=AliasTupleImpl!T; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AliasTuple
looks a limited version of std.typetuple.Pack
.
The one exception is the test for
Here's what the updated pull looks like with these changes: struct AliasTupleTuple(U...) { }
/**
* AliasTuple is a more general version of $(XREF typetuple, TypeTuple).
* AliasTuple instances can be compared against one another in $(D is) expressions.
*/
template AliasTuple(T...)
{
alias AliasTuple = AliasTupleTuple!T;
}
///
unittest
{
import std.typetuple : Alias;
alias fun = Alias!(a => a);
alias fun2 = fun;
int b;
alias b1 = b;
auto b2 = b;
static assert(is(AliasTuple!(double, "a", b, fun) == AliasTuple!(double, "a", b1, fun2)));
static assert(!is(AliasTuple!(double, "a", b, fun) == AliasTuple!(double, "a", b2, fun2)));
}
/**
* Tests whether $(D S) is an aliasable symbol.
*/
template isAliasable(alias S)
{
enum isAliasable = true;
}
/// ditto
template isAliasable(T)
{
enum isAliasable = false;
}
///
unittest
{
struct A1(T) { }
struct A2 { }
template A3(T)
{
struct A { }
}
struct A4(alias fun, T...) { }
static assert(!isAliasable!(double));
static assert(isAliasable!("foo"));
static assert(isAliasable!(A1));
static assert(isAliasable!(A1!double));
static assert(isAliasable!(A2));
static assert(isAliasable!(a=>a));
enum b = 1;
static assert(isAliasable!b);
}
private template isComparableAtCompileTime(alias T1, alias T2)
{
static assert(T1 == T2);
}
/**
* Tests for equality between 2 symbols (types/templates/values etc).
*/
template isSame(S...) if (S.length == 2)
{
static if (__traits(compiles, isComparableAtCompileTime!(S[0], S[1])))
{
enum isSame = S[0] == S[1];
}
else static if (isAliasable!(S[0]) && isAliasable!(S[1]))
{
enum isSame = __traits(isSame, S[0], S[1]);
}
else static if (__traits(compiles, is(S[0] == S[1])))
{
enum isSame = is(S[0] == S[1]);
}
else
enum isSame = false; // eg: "foo" , int
}
///
unittest
{
struct A1(T) { }
struct A2 { }
template A3(T)
{
struct A { }
}
struct A4(alias fun, T...) { }
static assert(isSame!(double, double));
static assert(isSame!(A1, A1));
static assert(isSame!(A1!int, A1!int));
static assert(!isSame!(A1!int, A1!float));
static assert(isSame!("foo", "foo"));
static assert(!isSame!("foo", "bar"));
static assert(!isSame!(a => a, a => a));
auto fun = (int a) => a;
static assert(isSame!(fun, fun));
static assert(!isSame!("foo", int));
}
/**
* Retrieves template symbol from a template instance.
* $(RED Note:) Does not yet work with template function instances.
*/
template GetTemplateSymbol(T : TI!TP, alias TI, TP...)
{
alias GetTemplateSymbol = TI;
}
/// ditto
template GetTemplateSymbol(alias T : TI!TP, alias TI, TP...)
{
// TODO: how come this doesn't work with functions?
alias GetTemplateSymbol = TI;
}
///
unittest
{
struct A1(T) { }
template A3(T)
{
struct A { }
}
// struct _S4(alias fun, T...) { } // note: compiler bug with local instances
static assert(isSame!(GetTemplateSymbol!(A1!double), A1));
static assert(isSame!(GetTemplateSymbol!(_S4!(a => a, int)), _S4));
static assert(isSame!(GetTemplateSymbol!(A3!(int)), A3));
}
///
version(unittest)
{
struct _S4(alias fun, T...) { }
}
/**
* Retrieves template arguments from a template instantiation.
* $(RED Note:) Does not yet work with template function instances.
*/
template GetTemplateArguments(T : TI!TP, alias TI, TP...)
{
alias GetTemplateArguments = TP;
}
/// ditto
template GetTemplateArguments(alias T : TI!TP, alias TI, TP...)
{
// TODO: how come this doesn't work with functions?
alias GetTemplateArguments = TP;
}
///
unittest
{
struct A1(T) { }
struct A4(alias fun, T...) { }
import std.typetuple;
static assert(is(AliasTuple!double == AliasTuple!(GetTemplateArguments!(A1!double))));
static assert(is(AliasTuple!("foo", int) == AliasTuple!(GetTemplateArguments!(A4!("foo", int)))));
}
/**
* Checks whether $(D S) is a template instance.
*/
template isTemplateInstance(S...) if (S.length == 1)
{
enum isTemplateInstance = is(typeof(GetTemplateSymbol!S));
}
///
unittest
{
struct A1(T) { }
struct A2 { }
template A3(T)
{
struct A { }
}
static assert(isTemplateInstance!(A1!double));
static assert(!isTemplateInstance!(A1));
static assert(!isTemplateInstance!(A2));
static assert(!isTemplateInstance!(A3));
static assert(isTemplateInstance!(A3!double));
static assert(!isTemplateInstance!(A3!double.A));
static assert(!isTemplateInstance!(int));
} |
I am speaking about documentation mostly here. If some generic utility gets into standard library, it needs to be perfectly clear what it should be used for and what not, in other words, it shouldn't rely on implementation-defined semantics. Especially when behaviour is as vague as here. |
There's now |
defines new std.traits templates:
These are useful generic traits that can be used
related discussions:
http://forum.dlang.org/post/mailman.1382.1371938670.13711.digitalmars-d@puremagic.com
http://d.puremagic.com/issues/show_bug.cgi?id=4265
In particular, GetTemplateParent, GetTemplateArguments avoid requiring templates to define internal aliases for type parameters, as is currently done in d modules (and always done in C++ templates). GetTemplateParent/GetTemplateArguments removes the need to introduce new compiler __traits.
These traits are also essential in a subsequent pull request I will make to fix std.traits.fullyQualifiedName + friends to work on templated types (currently fullyQualifiedName + friends fail on those)
'isSame' works with pretty much everything I've tried. It wraps around __traits(isSame, a==b) , is(a==b), a==b as required.
Caveats: