1

我写了一个小型的自包含库(仅依赖于 C++ 标准库),它有自己的内置 3D 矢量类:

namespace mylibrary {

    struct Vector {
        double x, y, z;

        // and constructors
        // like:
        Vector(double x, double y, double z);

        // and operators
    };

}

它应该与产生/使用 3D 矢量的其他代码交互。

现在,假设其他一些库,它具有:

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 向量的概念,但它当然是与我的库的向量不同的类型,即使语义相同。想想 Python 的鸭子类型:只要它以预期的方式运行,类型并不重要。

问题:

我可以使用什么机制来方便地使用我的库Vector作为参数otherlibrary::doSomething()

也就是说,能够这样写:

otherlibrary::doSomething( mylibrary::Vector(...) );

我当然可以构建我的Vector类,使其具有一个模板化的构造函数,该构造函数接受具有“x、y、z”成员或 的任何类型 T operator[],因此它几乎可以使用任何可以解释为 3D 向量的东西。有没有可能反过来做呢?

编辑:

当然,我可以让它依赖于另一个库,然后我可以重用另一个库的 3D 矢量抽象。这是不合理的,因为我的库是通用的,所以说使用 Eigen::Vector3d 作为我的向量是没有意义的,因为它可以在不使用 Eigen 的环境中使用。

最佳答案:

根据尼尔柯克的回答:

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};
    }
};

i 用于在enable_if多个重载函数和运算符可用时解决歧义;Eigen 是需要它的一个实际案例。

4

2 回答 2

2

是的,将转换运算符添加到您的 Vector 类。

operator otherlibrary::Vector3() const
{
    return otherlibrary::Vector3(x, y, z);
}

但这意味着您的向量现在将依赖于其他库..

为了避免依赖,没有办法完全按照你的要求去做。替代建议是如下所示的转换函数,它对向量类型进行了一些假设。

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)));

虽然非常冗长:(

实验!!我没有尝试过,也不知道它是否有效。关注:您的向量可以转换为任何需要 3 个构造函数参数的类,即使它没有意义

template<class T>
operator T() const
{
    return T(x, y, z);
}
于 2013-08-07T00:50:39.050 回答
0

很少有理由定义自己的vector3类型,这是一个严重的缺点。即使您对模板做了一些聪明的事情,它也可能与其他库中的类似“聪明”相冲突。

将您的运算符定义为自由函数,而不是成员,并std::array改为使用。如果您真的必须拥有自己的类,请定义一个to_array()返回标准类型的函数。任何理智的库都可以从中进行转换,即使array::data()将其视为 C 数组也是如此。

(提示:您可以引用和返回reinterpret_castC 样式的数组std::array &,以避免复制数据。)

于 2013-08-07T02:22:20.430 回答