简体   繁体   English

以Eigen类型为参数的泛型函数回调

[英]generic function callback with Eigen types as parameters

I'm trying to pass a function using Eigen objects as inputs and outputs as a callback to another function. 我试图将使用本对象作为输入和输出的函数传递给另一个函数。 I can't find a way to properly handle const parameters. 我找不到正确处理const参数的方法。 For example I have this copy function : 例如,我有此复制功能:

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

I know that output parameters can be considered a bad practice but I'm trying to follow the coding guidelines of libigl . 我知道输出参数可能被认为是不好的做法,但是我正在尝试遵循libigl的编码准则 As a reference I call this function within another function, this will work. 作为参考,我在另一个函数中调用此函数,它将起作用。

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

Now I would like genericity on the copy function. 现在,我想对复制函数进行泛型。

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

But automatic template deduction from parameters will not deduce the template parameters for the callback. 但是,从参数自动推断模板不会推断出回调的模板参数。 The only solution I found so far is this ugly overload, I'm not proud of it, and open for suggestions. 到目前为止,我发现的唯一解决方案是这种丑陋的重载,我对此并不感到骄傲,并且愿意提出建议。

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

and this works, but I can't manage to handle a const in the first parameter of generic : 这可行,但我无法在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 ;
}

Here is the error 这是错误

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

The full example is in the following snippet. 完整的示例在以下片段中。

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

To handle overloads, pass functor instead of function, something like: 要处理重载,请传递函子而不是函数,例如:

auto copy_functor = [](auto&& source, auto&& dest){ return copy(source, dest); }

generic(m1, m2, copy_functor);
generic_const(m1, m2, copy_functor);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM