为基本数据类型和 Eigen 数据类型编写模板函数
Writing a template function for basic and Eigen data types
我如何编写一个同时接受基本数据类型(int、float、double 等)和 Eigen 库类型(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 中,从 Vector2f v 到 Vector2d 的转换是使用 v.cast<double>()
完成的,因此模板参数是标量的数据类型,而不是新类型本身。
我遇到的麻烦(至少我认为这是主要问题)是我不知道如何将这两个模板放在一起。 Eigen 可能应该是第一个的特化,但这有可能吗?模板本身编译,但例如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>
。为此,我遍历所有元素并使用所需的函数转换每个元素。因此,如果有更好的方法来转换 std::vector 的 Eigen 类型,这就是我所需要的。
您可以使用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 */
}
这样一来,一切都在一个函数中,我发现语法更清晰一些。
我如何编写一个同时接受基本数据类型(int、float、double 等)和 Eigen 库类型(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 中,从 Vector2f v 到 Vector2d 的转换是使用 v.cast<double>()
完成的,因此模板参数是标量的数据类型,而不是新类型本身。
我遇到的麻烦(至少我认为这是主要问题)是我不知道如何将这两个模板放在一起。 Eigen 可能应该是第一个的特化,但这有可能吗?模板本身编译,但例如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>
。为此,我遍历所有元素并使用所需的函数转换每个元素。因此,如果有更好的方法来转换 std::vector 的 Eigen 类型,这就是我所需要的。
您可以使用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 */
}
这样一来,一切都在一个函数中,我发现语法更清晰一些。