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 behavior". 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.