Typeof woes

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Aug 21 07:45:45 PDT 2013


On Wed, Aug 21, 2013 at 08:32:09AM +0200, Marek Janukowicz wrote:
> H. S. Teoh wrote:
[...]
> > To get around this, you will need to use static if, maybe something
> > like this:
> > 
> > void list() {
> > // Warning: untested code
> > foreach(s; __traits(derivedMembers, typeof(this))) {
> > static if (is(typeof(__traits(getMember, this, s)) type)) {
> > // here, 'type' is bound to the type of
> > // the member.
> > }
> > }
> > }
> > 
> > This uses the is(X Y) form, where if X is a valid type, then it gets
> > aliased to Y inside the static if block. (I have to admit I'm not
> > that pleased with D's is-expressions due to their confusing syntax,
> > but they do work and are quite a powerful tool to use once you
> > understand them.)
> 
> This code works, thank you. However, if I may share my newbie
> impression - current traits implementation looks not complete to me.
> What I want to do is to process those members that are of certain type
> - instead of a nice one- liner to identify those, I already need two
> and the first (the one you provided above) looks like a hack to me,
> because I have to check if some expression is valid. The whole issue
> (which to me looks like a quite standard metaprogramming task) already
> took me a few hours (and also some time of you and the other helpful
> guys) and I can't get rid of the impression either the docs are
> lacking or we could use some more traits.

>From what I can tell, the traits are designed to be minimal, just enough
to cover what needs to be done, so sometimes they may not have the
nicest or most concise interfaces. You can always add some syntactic
sugar to it using templates, of course.

That, and the docs probably could use a facelift. :) This isn't the
first time somebody's found the docs too obscure or unhelpful.

In any case, you're not the first one who found the __traits syntax
cumbersome. I know I did when I first started using it. It's probably
too late to change __traits syntax, but I can see adding some nice
wrapper templates to std.traits to make these things less annoying.
Some stuff is already there, but a few more would make introspection
easier.


> >> What's even more interesting it's just alias problem, the
> >> expression "typeof(__traits(getMember, this, s))" might be used eg.
> >> in static if even for enums.
> >> 
> >> Is this a bug or do I miss something (again)?
> > [...]
> > 
> > Are you sure about that? That doesn't sound right to me.
> 
> Yes, I'm sure, here goes modified code:
> import std.stdio;
> 
> class A {
> 
>   int a;
>   enum Smth { A };
> 
>   void list () {
>     foreach( s; __traits(derivedMembers, typeof(this))) {
>       //alias type = typeof(__traits(getMember, this, s));
>       static if (is (typeof(__traits(getMember, this, s)) == int)) {
>         writefln ("%s is int", s );
[...]

Ah, you're putting it inside an is(...) expression, that's why it
"works". :) The whole point of is(...) is to check if a particular
expression makes sense (aka "has a type", the idea being that if the
expression is invalid, like if you try to perform arithmetic on types or
if use a type as a value). So naturally, it suppresses type-related
errors inside and just returns false instead.

This is one of the dark corners in D where things are more obscure than
they need to be. The whole syntax/semantics of is(...), while quite
complete and functional, leaves a lot to be desired in terms of
readability / usability. A lot of newcomers have trouble with it,
including myself when I first encountered it.

In any case, if you're just looking for members of a particular known
type, then using is(typeof(__traits(getMember, ...)...)) should be good
enough.


T

-- 
Political correctness: socially-sanctioned hypocrisy.


More information about the Digitalmars-d-learn mailing list