Search code examples
c++implicit-conversionglm-mathbulletphysics

Implicit casting similar types from separate libraries to work together seamlessly together in C++


I'm using GLM and Bullet Physics and they each have their own type of vector types - glm::vec3 and btVector3. They are exactly the same data structures but they annoy me because they don't go together nicely. A lot of manual conversions have to happen.

Suppose I have a function foo(btVector3 f) and I want to pass a glm::vec3 as the parameter without having convert it to btVector3 beforehand, similar to how you can pass a const char * into a function that requires an std::string without having to cast it to string first.

Now I don't want to go into each of these libraries and put operators into the classes manually, only for that to be ruined if I update the libraries (assuming that's even allowed by their license). How would I make one type of vector automatically cast to the other and vice versa from within my own project, without going inside and editing the libraries themselves?


Solution

  • As far as I know, you cannot implement implicit conversion operators outside of the class. What I'm used to do in similar situations is just creating a couple of simple conversion functions with really short (but still understandable) names. So in your case, assuming that each of vectors have just 3 fields x, y, z, such functions would look like this

    inline btVector3 glm2bt(const glm::vec3& vec)
    {
        return { vec.x, vec.y, vec.z };
    }
    
    inline glm::vec3 bt2glm(const btVector3& vec)
    {
        return { vec.x, vec.y, vec.z };
    }
    

    See full sample at Coliru

    Then, if you have a function foo working with one of the types

    void foo(glm::vec3 v) { /* implementation */ }
    

    and you want to feed an object of another type to it, the code at the caller site will still be quite compact

    btVector3 vec = getVectorFromSomeWhere();
    foo(bt2glm(vec));
    

    Actually, based on my personal experience with similar situations, in retrospective I believe that it is a better solution than if I were able to define an implicit conversion operator you're looking for. At a cost of typing just several more symbols you get an easy way to locate all the inter-dependencies between those third-party libraries. Which may become very important at a certain point in life of your code base.