Thread overview
Why does this code only work with `T` and not `typeof(T)`?
Jan 04, 2023
thebluepandabear
Jan 04, 2023
Ali Çehreli
Jan 04, 2023
thebluepandabear
January 04, 2023

I am using the CSFML D bindings, and I am creating my own draw template function.

I first check that the object passed in is of the appropriate type, and if it is, I call the appropriate function:

template isDrawable(T) {
    enum isDrawable = is(T == sfCircleShape*) || is(T == sfRectangleShape*) || is(T == sfText*) || is(T == sfSprite*);
}

void sfRenderWindowExt_draw(T)(sfRenderWindow* renderWindow, T obj) {
    static assert(isDrawable!T, format("Cannot call any draw method on type %s", T.stringof));

    if (is(T == sfCircleShape*)) {
        renderWindow.sfRenderWindow_drawCircleShape(cast(sfCircleShape*)obj, null);
    } else if (is(T == sfRectangleShape*)) {
        renderWindow.sfRenderWindow_drawRectangleShape(cast(sfRectangleShape*)obj, null);
    } else if (is(T == sfText*)) {
        renderWindow.sfRenderWindow_drawText(cast(sfText*)obj, null);
    } else if (is(T == sfSprite*)) {
        renderWindow.sfRenderWindow_drawSprite(cast(sfSprite*)obj, null);
    }
}

For some reason, if I replace the isDrawable template with the following (using typeof), the code does not compile:

template isDrawable(T) {
    enum isDrawable = is(typeof(T) == sfCircleShape*) || is(typeof(T) == sfRectangleShape*) || is(typeof(T) == sfText*) || is(typeof(T) == sfSprite*);
}

This is really strange, as I assumed that the two pieces of code were essentially the same.

Any help as to why this is the case would be appreciated.

January 03, 2023
On 1/3/23 20:11, thebluepandabear wrote:

> if I replace the `isDrawable` template with the
> following (using `typeof`), the code does not compile:

It must be because T is already a type. It's the same reason why the following code fails to compile:

void main() {
    alias T = int;
    alias TT = typeof(T);
}

Error: type `int` is not an expression

And the error message tells us typeof requires an expression. What you can do is to use T.init and the code should now work like the following does:

    alias TT = typeof(T.init);

Ali

January 04, 2023
On Wednesday, 4 January 2023 at 04:42:08 UTC, Ali Çehreli wrote:
> On 1/3/23 20:11, thebluepandabear wrote:
>
> > if I replace the `isDrawable` template with the
> > following (using `typeof`), the code does not compile:
>
> It must be because T is already a type. It's the same reason why the following code fails to compile:
>
> void main() {
>     alias T = int;
>     alias TT = typeof(T);
> }
>
> Error: type `int` is not an expression
>
> And the error message tells us typeof requires an expression. What you can do is to use T.init and the code should now work like the following does:
>
>     alias TT = typeof(T.init);
>
> Ali

Ok, that makes sense now, my mistake. I seem to have gotten the wrong impression that typeof is more flexible than it is.