我在机器人领域工作,这意味着我使用了大量处理3D几何的开源项目。由于类和数学往往相当简单,所以每个人似乎都实现了他们自己的Vector3D,Quaternion等版本,每个版本都有轻微的变化,例如vec.x,vec.X,vec.x()。因此,在一个项目中,可能需要在Eigen,ROS,Assimp,Bullet和相同基本类的其他版本之间进行转换。有没有一种简单或优雅的方法在C ++中执行此操作,并不需要从每个库到每个其他库的n ^ 2映射?
类似于:This SO question,但我无法编辑任何源库。
示例:
namespace a
{
class Vector
{
public:
double x, y, z;
};
} // namespace a
namespace b
{
class Vector
{
public:
double X, Y, Z;
};
} // namespace b
namespace c
{
class Vector
{
public:
double& x() { return mx; }
double& y() { return my; }
double& z() { return mz; }
private:
double mx, my, mz;
};
} // namespace c
int main()
{
a::Vector va;
b::Vector vb;
c::Vector vc = va + vb; // Ideal, but probably unrealistic goal
return 0;
}
修改:
如果有大约10个不同的几何库,则特定项目可能只使用其中的2-4个,因此我希望避免对所有未使用的库引入依赖关系。我希望有类似static_cast<b::Vec>(a::Vec)
或者
c::Vec vc = my_cvt<c::Vec>(vb + my_cvt<b::Vec>(va));
但我对模板和type_traits的理解相当薄弱。
答案 0 :(得分:3)
如果为每种矢量类型编写三个辅助函数来访问X
,Y
和Z
:
double X(const a::Vector& v) { return v.x; }
double Y(const a::Vector& v) { return v.y; }
double Z(const a::Vector& v) { return v.z; }
double X(const c::Vector& v) { return v.x(); }
double Y(const c::Vector& v) { return v.y(); }
//...
然后您可以轻松编写适用于任何类型的模板函数。 e.g:
template<typename V1, typename V2>
V1 operator+(const V1& v1, const V2& v2) {
return {X(v1)+X(v2), Y(v1)+Y(v2), Z(v1)+Z(v2)};
}
template<typename V1, typename V2>
V1 convert(const V2& v) {
return {X(v), Y(v), Z(v)};
}
int main() {
a::Vector va;
b::Vector vb;
auto vc = convert<c::Vector>(va + vb);
}
答案 1 :(得分:1)
好吧,只需定义operator+
功能和您不切实际的目标&#39;会实现:
c::Vector operator+(const a::Vector& a, const b::Vector& b) {
return {a.x+b.X, a.y+b.Y, a.z+b.Z};
}
您的小代码段就可以了。
修改强>
如果您不想定义很多功能,并假设您无法从a和b更改Vector版本,请通过添加这些构造函数来修改矢量类:
Vector(a::Vector a) : mx(a.x), my(a.y), mz(a.z) {}
Vector(b::Vector b) : mx(b.X), my(b.Y), mz(b.Z) {}
然后只定义一个只处理c类的运算符:
c::Vector operator+(c::Vector a, c::Vector b) {
return {a.x()+b.x(), a.y()+b.y(), a.z()+b.z()};
}
您的代码段将用于声明数千个运算符
编辑2
如果您希望类型与图书馆的类型兼容,您可以将转换运算符添加到结构中,例如,如果您希望您的类型可以使用Vector a转换,请在您的类中添加此函数:< / p>
operator a::Vector() const {
// return a a::Vector from our c::Vector
return a::Vector{mx, my, mz};
}
答案 2 :(得分:1)
我看到这是一个老问题,但请查看Boost QVM。