Я пытаюсь передать функцию, используя 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) ;
}
и это работает, но мне не удается обработать const
в первом параметре generic
:
//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 ;
}