Thread overview
Fastest way to check if the bottom-class of a class reference is any of a set of classes
Dec 16, 2019
Per Nordlöw
Dec 16, 2019
H. S. Teoh
Dec 17, 2019
Per Nordlöw
December 16, 2019
What is the fastest way to check whether a class reference is an instance of a
bottom equal to any in a set of classes? My current try is something like

class C {}

class X : C {}
class Y : C {}
class Z : C {}
...

bool pred(scope const Object object)
{
    return (cast(const(X))object ||
            cast(const(Y))object ||
            cast(const(Z))object ||
            ...);
}

or is it better to switch on the non-scoped (via some existing string-to-string
function `unscoped`) part of the `typeid(object).name` like

bool pred(scope const Object object)
{
    const name = typeid(object).name.unscope;
    import std.algorithm.comparison : among;
    return name.among!(X.stringof,
                       Y.stringof,
                       Z.stringof,
                       ...);
}

?
December 16, 2019
On Mon, Dec 16, 2019 at 02:38:59PM +0000, Per Nordlöw via Digitalmars-d-learn wrote:
> What is the fastest way to check whether a class reference is an instance of
> a
> bottom equal to any in a set of classes? My current try is something like
> 
> class C {}
> 
> class X : C {}
> class Y : C {}
> class Z : C {}
> ...
> 
> bool pred(scope const Object object)
> {
>     return (cast(const(X))object ||
>             cast(const(Y))object ||
>             cast(const(Z))object ||
>             ...);
> }
[...]

What about:

	class X {}
	class Y {}
	class Z {}

	bool pred(scope const Object object)
	{
		import std.meta : AliasSeq;

		// make this as long as you need
		alias MyClasses = AliasSeq!(X, Y, Z);

		static foreach (C; MyClasses)
		{
			if (cast(const(C)) object) return true;
		}
		return false;
	}


T

-- 
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
December 16, 2019
On 12/16/19 9:38 AM, Per Nordlöw wrote:
> What is the fastest way to check whether a class reference is an instance of a
> bottom equal to any in a set of classes? My current try is something like
> 
> class C {}
> 
> class X : C {}
> class Y : C {}
> class Z : C {}
> ....
> 
> bool pred(scope const Object object)
> {
>      return (cast(const(X))object ||
>              cast(const(Y))object ||
>              cast(const(Z))object ||
>              ...);
> }
> 
> or is it better to switch on the non-scoped (via some existing string-to-string
> function `unscoped`) part of the `typeid(object).name` like
> 
> bool pred(scope const Object object)
> {
>      const name = typeid(object).name.unscope;
>      import std.algorithm.comparison : among;
>      return name.among!(X.stringof,
>                         Y.stringof,
>                         Z.stringof,
>                         ...);
> }
> 
> ?

I'd compare the typeid directly:

auto tid = typeid(object);

return(tid is typeid(X) || tid is typeid(Y) || tid is typeid(Z) || ...)

If you are doing a cast(const(X))object, what you are doing is each time traversing the linked-list of typeids anyway doing the same as the above, but doing extra work. So this should be faster.

-Steve
December 17, 2019
On Monday, 16 December 2019 at 18:01:06 UTC, Steven Schveighoffer wrote:
> I'd compare the typeid directly:
>
> auto tid = typeid(object);
>
> return(tid is typeid(X) || tid is typeid(Y) || tid is typeid(Z) || ...)
>
> If you are doing a cast(const(X))object, what you are doing is each time traversing the linked-list of typeids anyway doing the same as the above, but doing extra work. So this should be faster.
>
> -Steve

Great. Thanks.

Because we're only interested in non-abstract classes I adjusted your code to

    static foreach (Type; AliasSeq!(...))
    {
        static assert(!__traits(isAbstractClass, Type));
        if (zingid is typeid(Type)) { return true; }
    }