How to use Nim's `of` operator with generics?

bluenote10

Consider a type hierarchy, where the base object is non-generic, but sub-types are:

type
  TestBase = ref object of RootObj

  DerivedA = ref object of TestBase
  DerivedB[T] = ref object of TestBase
    field: T

proc testProc(x: TestBase) =
  if x of DerivedB:   # <= what to do here
    echo "it's a B!"
  else:
    echo "not a B"

Using the of operator like this won't compile, because it expects object types. What does work is e.g. to match for specific types like DerivedB[int], or making the proc itself generic in T, which is meaningless when passing in a DerivedA.

Is there a way to solve this problem generically without resorting to methods and dynamic dispatch?

zah

The easiest solution here is to introduce a dummy base type for all of the generic derived types, with the only purpose of assisting in such checks. Here is an example:

type
  TestBase = ref object of RootObj

  DerivedA = ref object of TestBase

  # I'm using illustrative names here
  # You can choose something more sensible
  DerivedDetector = ref object of TestBase

  DerivedB[T] = ref object of DerivedDetector
    field: T

proc testProc(x: TestBase) =
  if x of DerivedDetector: # This will be true for all derived types
    echo "it's a B!"
  else:
    echo "not a B"

testProc DerivedB[int](field: 10)
testProc DerivedA()

This solution won't increase the size of the objects and it doesn't introduce any run-time overhead in typical code.

If you can't modify the inheritance hierarchy (it may be part of a third-party library), there is a much more complicated solution based on the getTypeInfo proc from the system module. This proc returns an opaque pointer that can be used as an identifier for the type. You'll have to register all derived types with their identifiers in a hash table (you can do this at the start of the program) and then use that to make run-time checks against the type-info pointers of the input values in the proc.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related