我写了一个小型的独立库(仅依赖于 C++ 标准库),它有自己的内置 3D vector 类:
namespace mylibrary {
struct Vector {
double x, y, z;
// and constructors
// like:
Vector(double x, double y, double z);
// and operators
};
}
它应该与其他生成/使用 3D vector 的代码交互。
现在,假设其他一些库,它有:
namespace otherlibrary {
struct Vector3 {
// some different definition
// And is still able to construct from 3 values
Vector3(double x, double y, double z);
};
doSomething(const Vector3& point); // do something with the point
}
这个其他库可以是 3D 建模工具或 3D 引擎的插件 API。它也有 3D vector 的概念,但它当然与我的库的 vector 不同,即使语义相同。想想 Python 的鸭子类型:类型并不重要,只要它以预期的方式运行即可。
问题:
我可以使用什么机制使我的库的 Vector
方便地用作 otherlibrary::doSomething()
的参数?
也就是说,能够这样写:
otherlibrary::doSomething( mylibrary::Vector(...) );
我当然可以构建我的 Vector
类,使其具有一个模板构造函数,该构造函数接受任何具有“x, y, z”成员或 operator[]
的类型 T,所以它几乎可以消耗任何可以解释为 3D vector 的东西。是否可以反过来做?
编辑:
当然,我可以让它依赖于另一个库,然后我可以重用另一个库的 3D vector 抽象。这是不合理的,因为我的库是通用的,说使用 Eigen::Vector3d 作为我的 vector 是没有意义的,因为它可以在不使用 Eigen 的环境中使用。
最佳答案:
根据 Neil Kirk 的回答:
struct Vector {
using value_type = double;
template<class T,
class = typename enable_if<
is_constructible<T, value_type,value_type,value_type>::value
>::type>
operator T() const
{
return T{x, y, z};
}
};
enable_if
用于在多个重载函数和运算符可用时解决歧义; Eigen 是一个需要它的实际案例。
最佳答案
是的,将转换运算符添加到您的 Vector 类。
operator otherlibrary::Vector3() const
{
return otherlibrary::Vector3(x, y, z);
}
但这意味着您的 vector 现在将依赖于其他库..
为了避免依赖,没有办法完全按照你的要求去做。替代建议是如下所示的转换函数,它对 vector 类型做出了一些假设。
template<class T, U>
T ConvertVector3(const U& v)
{
return T(v.x, v.y, v.z);
}
otherlibrary::doSomething(ConvertVector3<otherlibrary::Vector3>(mylibrary::Vector(x, y, z)));
虽然很冗长:(
实验性的!!我没有尝试过,也不知道它是否有效。关注点:您的 vector 可以转换为任何需要 3 个构造函数参数的类,即使它没有意义
template<class T>
operator T() const
{
return T(x, y, z);
}
关于c++ - 设计一个可以与其他库相互转换的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18092866/