我正在使用GLM和Bullet Physics,它们各自都有自己的矢量类型 - glm::vec3
和btVector3
。它们是完全相同的数据结构,但它们让我烦恼,因为它们不能很好地结合在一起。必须进行大量手动转换。
假设我有一个函数foo(btVector3 f)
,我希望传递一个glm::vec3
作为参数而不事先将其转换为btVector3
,类似于传递{{1}的方式进入一个需要const char *
的函数,而不必先将它强制转换为字符串。
现在我不想进入每个库并手动将std::string
放入类中,只有在我更新库时才会被破坏(假设他们的许可证甚至允许)。如何在我自己的项目中将一种类型的矢量自动转换为另一种,反之亦然,而不进入内部并自行编辑库?
答案 0 :(得分:2)
似乎没有一种方法可以在不修改至少一个类的情况下使两个类隐式可转换:
来自C ++规范
在考虑构造函数或用户定义的参数时 转换功能,只允许一个标准转换序列 (否则用户定义的转换可以有效链接)。
和
表达式e被认为可以隐含地转换为T2 如果T2可以从e复制初始化,那就是声明T2 t = Ë;对于一些发明的临时性而言,形式良好(可以编译)。
如果你看看复制初始化意味着什么 http://en.cppreference.com/w/cpp/language/copy_initialization
只能使用转换构造函数,甚至不能使用赋值运算符。由于您无法向类中添加构造函数,因此您将无法使用派生类。但是,因为无法链接隐式转换(即编译器在使用中间类型将A转换为C时不会查找转换),所以在某些情况下至少需要显式转换。
然而,使用派生类的概念,它可能不如你想象的那么频繁。如果将任何中间向量变量声明为自己的类,则只需在将返回值从一个库直接传递给另一个库时显式强制转换。你可以做到这一点很好:MyVec v = GLM::GetVector(a,b,c); // returns GLM::vec3
Bullet::TransformV(v, matrix); // accepts btVector3
你的课程类似于:
class MyVec : GLM::vec3
{
public:
MyVec(GLM::vec3 *vec) {
....
}
MyVec(btVector3 *vec) {
....
}
operator btVector3*() const { ... }
}
答案 1 :(得分:1)
据我所知,你不能在类之外实现隐式转换运算符。我在类似情况下习惯做的只是创建一些简单的转换函数,其中包含非常简短(但仍然可以理解)的名称。
所以在你的情况下,假设每个向量只有3个字段x, y, z
,这样的函数看起来像这样
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 };
}
查看完整示例at Coliru
然后,如果你有一个函数foo
使用其中一种类型
void foo(glm::vec3 v) { /* implementation */ }
并且您希望向其提供另一种类型的对象,来电者网站的代码仍然非常紧凑
btVector3 vec = getVectorFromSomeWhere();
foo(bt2glm(vec));
实际上,根据我在类似情况下的个人经验,在回顾中我认为这是一个比我能够定义你正在寻找的隐式转换运算符更好的解决方案。只需键入几个符号,您就可以轻松找到这些第三方库之间的所有相互依赖关系。这可能会在代码库的某个特定时刻变得非常重要。