以特征类型作为参数的泛型函数回调
generic function callback with Eigen types as parameters
我正在尝试传递一个使用 Eigen 对象作为输入和输出作为另一个函数的回调的函数。我找不到正确处理const
参数的方法。例如,我有这个复制功能:
//a generic function copying a matrix into another
template<
typename DerivedV1,
typename DerivedV2
>
void copy
(
const Eigen::MatrixBase<DerivedV1> & v1,
Eigen::MatrixBase<DerivedV2> const & v2 //Eigen const hack, this is not const
)
{
Eigen::MatrixBase<DerivedV2> & v2_cast =
const_cast< Eigen::MatrixBase<DerivedV2> & >(v2) ;
v2_cast = v1 ;
}
我知道输出参数可以被认为是一种不好的做法,但我正在尝试遵循 libigl 的编码准则。作为参考,我在另一个函数中调用此函数,这将起作用。
//reference non generic behaviour
template<
typename DerivedV1,
typename DerivedV2
>
void reference
(
const Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2 //Eigen const hack not necessary for the example
)
{
copy(V1.row(0), V2.row(0)) ;
}
现在我想要复制函数的通用性。
//generic without constness,deduction fails with a template function as a parameter
template<
typename DerivedV1,
typename DerivedV2,
typename Callback
>
void generic
(
Eigen::MatrixBase<DerivedV1> & V1, //no const here, this is my problem
Eigen::MatrixBase<DerivedV2> & V2,
Callback callback
)
{
callback(V1.row(0), V2.row(0)) ;
}
但从参数中自动推导模板不会推导出回调的模板参数。到目前为止,我找到的唯一解决方案是这种丑陋的过载,我并不为此感到自豪,并愿意接受建议。
//overload to help template deduction
template<
typename DerivedV1,
typename DerivedV2
>
void generic
(
Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2,
void(*callback)(
const Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
)
{
generic<
DerivedV1,
DerivedV2,
void(*)(
const Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
>(V1, V2, callback) ;
}
这有效,但我无法处理generic
的第一个参数中的const
:
//desired generic with the const parameter
template<
typename DerivedV1,
typename DerivedV2,
typename Callback
>
void generic_const
(
const Eigen::MatrixBase<DerivedV1> & V1, //here is the desired const
Eigen::MatrixBase<DerivedV2> & V2,
Callback callback
)
{
callback(V1.row(0), V2.row(0)) ;
}
//attempt for an overload to help template deduction
template<
typename DerivedV1,
typename DerivedV2
>
void generic_const
(
const Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2,
void(*callback)(
const Eigen::MatrixBase< decltype(std::declval< const Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
)
{
generic_const<
DerivedV1,
DerivedV2,
void(*)(
const Eigen::MatrixBase< decltype(std::declval< const Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
>(V1, V2, callback) ;
}
int main() {
Eigen::Matrix3f m1 ;
m1.setRandom() ;
Eigen::Matrix3f m2 ;
m2.setRandom() ;
std::cout << "== random m1 ==" << std::endl << m1 << std::endl ;
std::cout << "== random m2 ==" << std::endl << m2 << std::endl ;
reference(m1, m2) ;
std::cout << "== reference behaviour ==" << std::endl << m2 << std::endl ;
m2.setRandom() ;
std::cout << "== random m2 ==" << std::endl << m2 << std::endl ;
//this is ok
generic(m1, m2, copy) ;
//this will not compile
std::cout << "== final m2 ==" << std::endl << m2 << std::endl ;
return 0 ;
}
这是错误
error: invalid initialization of reference of type
‘const Eigen::MatrixBase<const Eigen::Block<const Eigen::Matrix<float, 3, 3>, 1, 3, false> >&’
from expression of type
‘Eigen::DenseBase<Eigen::Matrix<float, 3, 3> >::ConstRowXpr’
{aka ‘const Eigen::Block<const Eigen::Matrix<float, 3, 3>, 1, 3, false>’}
完整示例在以下代码片段中。
#include <eigen3/Eigen/Dense>
#include <iostream>
#include <utility>
//a generic function copying a matrix into another
template<
typename DerivedV1,
typename DerivedV2
>
void copy
(
const Eigen::MatrixBase<DerivedV1> & v1,
Eigen::MatrixBase<DerivedV2> const & v2 //Eigen const hack, this is not const
)
{
Eigen::MatrixBase<DerivedV2> & v2_cast =
const_cast< Eigen::MatrixBase<DerivedV2> & >(v2) ;
v2_cast = v1 ;
}
//reference non generic behaviour
template<
typename DerivedV1,
typename DerivedV2
>
void reference
(
const Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2 //Eigen const hack is not necessary in this example
)
{
copy(V1.row(0), V2.row(0)) ;
}
//generic without constness,deduction fails with a template function as a parameter
template<
typename DerivedV1,
typename DerivedV2,
typename Callback
>
void generic
(
Eigen::MatrixBase<DerivedV1> & V1, //no const here this is my problem
Eigen::MatrixBase<DerivedV2> & V2,
Callback callback
)
{
callback(V1.row(0), V2.row(0)) ;
}
//overload to help template deduction
template<
typename DerivedV1,
typename DerivedV2
>
void generic
(
Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2,
void(*callback)(
const Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
)
{
generic<
DerivedV1,
DerivedV2,
void(*)(
const Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
>(V1, V2, callback) ;
}
//desired generic with the const parameter
template<
typename DerivedV1,
typename DerivedV2,
typename Callback
>
void generic_const
(
const Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2,
Callback callback
)
{
callback(V1.row(0), V2.row(0)) ;
}
//attempt for an overload to help template deduction
template<
typename DerivedV1,
typename DerivedV2
>
void generic_const
(
const Eigen::MatrixBase<DerivedV1> & V1,
Eigen::MatrixBase<DerivedV2> & V2,
void(*callback)(
const Eigen::MatrixBase< decltype(std::declval< const Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
)
{
generic_const<
DerivedV1,
DerivedV2,
void(*)(
const Eigen::MatrixBase< decltype(std::declval< const Eigen::MatrixBase<DerivedV1> &>().row(0)) > &,
Eigen::MatrixBase< decltype(std::declval< Eigen::MatrixBase<DerivedV2> &>().row(0)) > const &
)
>(V1, V2, callback) ;
}
int main() {
Eigen::Matrix3f m1 ;
m1.setRandom() ;
Eigen::Matrix3f m2 ;
m2.setRandom() ;
std::cout << "== random m1 ==" << std::endl << m1 << std::endl ;
std::cout << "== random m2 ==" << std::endl << m2 << std::endl ;
reference(m1, m2) ;
std::cout << "== reference behaviour ==" << std::endl << m2 << std::endl ;
m2.setRandom() ;
std::cout << "== random m2 ==" << std::endl << m2 << std::endl ;
generic(m1, m2, copy) ;
generic_const(m1, m2, copy) ;
std::cout << "== final m2 ==" << std::endl << m2 << std::endl ;
return 0 ;
}
要处理重载,请传递函子而不是函数,如下所示:
auto copy_functor = [](auto&& source, auto&& dest){ return copy(source, dest); }
generic(m1, m2, copy_functor);
generic_const(m1, m2, copy_functor);
相关文章:
- 链表的泛型函数remove()与成员函数remove)
- 以特征类型作为参数的泛型函数回调
- 传递非泛型函数的最有效方法是什么?
- 泛型函数反向打印任何矢量,编译器出错
- 是否可以在C++中创建泛型函数指针?
- 将泛型函数及其参数传递给元函数
- C++ 中的泛型函数持有者
- C++ 验证使泛型函数
- 两个不同流的泛型函数
- 如何覆盖 'const T&' 和 'T&&' 的泛型函数,其中 T 可以作为引用?
- 如何创建公开泛型函数的 DLL
- 为什么 std::apply 使用泛型函数失败
- 在某个值范围内生成 BST 的泛型函数
- 无法在循环中实例化泛型函数
- MISRA C++规则 14-5-1:在与类型关联的命名空间中声明的泛型函数模板的名称
- 使用泛型函数调用打印结构的所有嵌套成员变量
- C++ 使用数组作为参数创建泛型函数
- 泛型函数是否可以用于对结构求和
- C++为所有 std::sets 编写泛型函数
- 指向类成员函数的泛型函数指针