Question

The title is a bit ambiguous, so I'll provide an example of what I want to achieve:

class ValuePtr {
public:
    operator const void*() {
        return glm::value_ptr(*this); // value ptr won't work on this class 
                                      //(only works on glm types)
    }
};

class Mat4x4: public glm::mat4x4, public ValuePtr {
    // ...but would work here
};
class Vec3: public glm::vec3, public ValuePtr {
    // ...and here.
}

Is something like this possible in some way?

glm::value_ptr does only work on glm types like glm::mat4x4, glm::vec3, etc. So the above seen method would work if I implemented it directly in the derived classes, but they should all define operator const void* the exact same way. I want a trait-like behavior: Define it in the common base class, while the definition only works in the derived classes.


Thanks to the answer, this is the solution I'll use:

template<class T>
class ValuePtr: public T {
public:
    operator const void*() {
        return glm::value_ptr(*this);
    }
};

class Mat4x4: public ValuePtr<glm::mat4x4> {
};
Was it helpful?

Solution

Edit: I think I understand the problem now based on additional comments/edits. My next suggestion is to try a template:

template<typename GlmType>
class ValuePtr {
private:
   const GlmType& m_glm;

public:
   ValuePtr(const GlmType& glm)
     :m_glm(glm)
   {
   }

   operator const void*() {
      return glm::value_ptr(m_glm);
   }
};

class Mat4x4: public glm::mat4x4, public ValuePtr<Mat4x4> {
public:
   Mat4x4()
      : ValuePtr(*this)
   {
   }
};

etc. If you need everyone to have a common base class, you'd just need another layer above the templated one.

Original:

I'm not entirely sure what you need to do, so I'll try to cover all the bases. One possibility is that the base class ValuePtr doesn't need operator const void*() at all. In that case, just move it to Mat4x4:

class ValuePtr {
};

class Mat4x4: public glm::mat4x4, public ValuePtr {
    operator const void*() {
        return glm::value_ptr(*this);
    }
};

But maybe you want to have the function in both classes, and do something different in each case. I don't know what you'd want the base version to do, so let's just have it return null:

class ValuePtr {
   operator const void*() {
      return nullptr;
   }    
};

class Mat4x4: public glm::mat4x4, public ValuePtr {
   operator const void*() {
      return glm::value_ptr(*this);
   }
};

Finally, maybe you'll be deriving multiple classes from ValuePtr, and all of them need to be castable to const void*, but there's no reasonable way to implement that in the base itself. In that case, use a pure virtual function:

class ValuePtr {
    virtual operator const void*() = 0;
};

class Mat4x4: public glm::mat4x4, public ValuePtr {
   virtual operator const void*() override {
      return glm::value_ptr(*this);
   }
};

(the override keyword is optional, and actually may not work depending on what compiler you have).

OTHER TIPS

You mean like this?

template<class GLM_THING> class has_value_ptr {
  has_value_ptr(const GLM_THING& data)
  : _glmData(data) { }
public:
  operator void*() {
    return &_glmData;
  }

  GLM_THING& glmData() { return _glmData; }
  const GLM_THING& glmData() const { return _glmData; }

private:    
  GLM_THING _glmData;
};

class Mat4x4 : public has_value_ptr<glm::mat4x4> {
public:
  Mat4x4(const glm::mat4x4& data)
  : has_value_ptr<glm::max4x4>(data)
  {
  }
  ...
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top