Goals:
- Support bidirectional type lookups. E.g. finding the base type of a field was supported, but not the other way around. This also removes the todo in get_vector_type. To achieve this, types have to be registered up-front.
- Separate CPPType from other "type traits". For example, previously ValueOrFieldCPPType adds additional behavior on top of CPPType. Previously, it was a subclass, now it just contains a reference to the CPPType it corresponds to. This follows the composition-over-inheritance idea. This makes it easier to have self-contained "type traits" without having to put everything into CPPType.