禁用 Eigen 表达式到 const 引用的临时绑定
Disable temporary binding of Eigen expression to const references
我正在尝试编写一个仅接受通过 const
引用传递的左值特征表达式的函数。我的第一个想法是只保留重载 const Eigen::MatrixBase<Derived>&
和 delete
和 Eigen::MatrixBase<Derived>&&
一个。令我惊讶的是,delete
d 函数不是重载候选集的一部分。所以我尝试了下面的代码
#include <iostream>
#include <Eigen/Dense>
#define PRINT_MY_NAME std::cout << __PRETTY_FUNCTION__ << '\n'
template<typename Derived>
void f(const Eigen::MatrixBase<Derived>&) // (1)
{
PRINT_MY_NAME;
}
template<typename Derived>
void f(Eigen::MatrixBase<Derived>&&) // (2)
{
PRINT_MY_NAME;
}
int main()
{
Eigen::MatrixXd A;
f(A); // invokes (1)
f(A + A); // invokes also (1) !!!
}
输出 (gcc5.2)
void f(const Eigen::MatrixBase&) [with Derived = Eigen::Matrix < double, -1, -1>]
void f(const Eigen::MatrixBase&) [with Derived = Eigen::CwiseBinaryOp < Eigen::internal::scalar_sum_op < double>, const Eigen::Matrix < double, -1, -1>, const Eigen::Matrix < double, -1, -1> >]
很明显没有考虑右值重载。现在我很清楚第二个不是更好的匹配,因为我传递了一个右值特征表达式,它可以转换为 Eigen::MatrixBase<>
,但不是完全相同的类型。现在我的问题来了:
- 如何禁用或检测作为
f
参数传递的右值特征表达式?问题在于表达式可以具有任意类型(Eigen 使用表达式模板),例如 CwiseBinaryOp<...CwiseBinaryOp<...>>
等。这是一个更大的问题的一部分,在这个问题中我有一个类似于实用程序 make 的函数,它接受一个左值并将其绑定到 class 中的 const
引用表达式。如果表达式是一个右值,那么所有的赌注都不成立,因为引用绑定不是通过构造函数参数传播的,所以我想禁止传递右值特征表达式。
我想我找到了原因:表达式模板 A + A
的结果是 const
,因此存在 CV 不匹配。将 const
添加到第二个重载中:
template<typename Derived>
void f(const Eigen::MatrixBase<Derived>&&) // (2)
{
PRINT_MY_NAME;
}
我正在尝试编写一个仅接受通过 const
引用传递的左值特征表达式的函数。我的第一个想法是只保留重载 const Eigen::MatrixBase<Derived>&
和 delete
和 Eigen::MatrixBase<Derived>&&
一个。令我惊讶的是,delete
d 函数不是重载候选集的一部分。所以我尝试了下面的代码
#include <iostream>
#include <Eigen/Dense>
#define PRINT_MY_NAME std::cout << __PRETTY_FUNCTION__ << '\n'
template<typename Derived>
void f(const Eigen::MatrixBase<Derived>&) // (1)
{
PRINT_MY_NAME;
}
template<typename Derived>
void f(Eigen::MatrixBase<Derived>&&) // (2)
{
PRINT_MY_NAME;
}
int main()
{
Eigen::MatrixXd A;
f(A); // invokes (1)
f(A + A); // invokes also (1) !!!
}
输出 (gcc5.2)
void f(const Eigen::MatrixBase&) [with Derived = Eigen::Matrix < double, -1, -1>]
void f(const Eigen::MatrixBase&) [with Derived = Eigen::CwiseBinaryOp < Eigen::internal::scalar_sum_op < double>, const Eigen::Matrix < double, -1, -1>, const Eigen::Matrix < double, -1, -1> >]
很明显没有考虑右值重载。现在我很清楚第二个不是更好的匹配,因为我传递了一个右值特征表达式,它可以转换为 Eigen::MatrixBase<>
,但不是完全相同的类型。现在我的问题来了:
- 如何禁用或检测作为
f
参数传递的右值特征表达式?问题在于表达式可以具有任意类型(Eigen 使用表达式模板),例如CwiseBinaryOp<...CwiseBinaryOp<...>>
等。这是一个更大的问题的一部分,在这个问题中我有一个类似于实用程序 make 的函数,它接受一个左值并将其绑定到 class 中的const
引用表达式。如果表达式是一个右值,那么所有的赌注都不成立,因为引用绑定不是通过构造函数参数传播的,所以我想禁止传递右值特征表达式。
我想我找到了原因:表达式模板 A + A
的结果是 const
,因此存在 CV 不匹配。将 const
添加到第二个重载中:
template<typename Derived>
void f(const Eigen::MatrixBase<Derived>&&) // (2)
{
PRINT_MY_NAME;
}