为基本数据类型和特征数据类型编写模板函数

Writing a template function for basic and Eigen data types

本文关键字:数据类型 函数 特征      更新时间:2023-10-16

如何编写一个同时采用基本数据类型(int、float、double…)和特征库类型(Vector2f、Vector4d、Matrix4f…)的函数?具体来说,我想要一个将提供的参数强制转换为N.类型的强制转换函数

例如:

float x1 = cast<float>(1);
double x2 = cast<double>(2.0);
Vector2d x3 = cast<double>(Vector2f(3.0f, 3.0f));
Vector2f x4 = cast<float>(Vector2i(4, 4));

简单的部分:

template<typename T, typename N>
N cast(const T& source) const
{
    return static_cast<N>(source);
}

铸造特征类型:

template<typename T, typename N>
Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<typename Eigen::internal::traits<T>::Scalar, N>, const T> cast(const Eigen::MatrixBase<T>& source) const
{
    return source.cast<N>();
}

在Eigen中,从Vector2fv到Vector2d的转换是用v.cast<double>()完成的,因此模板参数是标量的数据类型,而不是新类型本身。

我遇到的麻烦(至少我认为这是主要问题)是我不知道如何将这两个模板放在一起。特征一可能是第一个的特殊化,但这可能吗?模板本身会编译,但例如cast<Vector2f, double>(Vector2f::Zero())不会编译,因为"static_cast":无法从"const Eigen::Vector2f"转换为"double"

该怎么办?C++11解决方案非常受欢迎,但请慢慢键入,因为我不是模板向导。

更新:我需要这一点的原因是,我希望能够方便地转换容器的内容,std::vector<T>std::vector<N>,例如std::vector<Vector2f>std::vector<Vector2d>,也可以从std::vector<float>std::vector<double>。为此,我循环遍历所有元素,并使用所需的函数强制转换每个元素。因此,如果有更好的方法来投射Eigen类型的std::向量,这将是我所需要的。

您可以使用std::enable_if将常规版本仅限于算术类型:

template<typename T, typename N>
typename std::enable_if<std::is_arithmetic<T>::value,N>::type
cast(const T& source) const {
  return static_cast<N>(source);
}

对于C++17,还有另一种解决方案,我个人认为它更优雅,使用if constexpr:

template<typename T, typename N>
std::conditional<std::is_arithmetic<T>::value, N, /* your Eigen return type here */>::type
cast( const T& source ) {
    if constexpr( std::is_arithmetic<T>::value )
        return static_cast<N>(source);
    else
        /* Eigen cast */
}

这样一来,所有这些都在一个函数中,我发现语法更清晰了。