Then you just have to make the pointers/iterators and subscript operators use that type information information to figure out how to move to the next element. No templates needed, because the type information is stored with the objects.
You may need templates when you actually dereference your pointers/iterators, to make them return the correct type. Alternatively you can still make operators * and -> work by returning a generic object type that can be cast to any object. Or just use BYTE.