我为operator<
实现了一个比较运算符Eigen::VectorXd
,有时候,我需要将一个比较函数传递给我的另一个函数,我厌倦了将operator<
包装到{{} 1}},所以我认为[](const VectorXd& v1, const VectorXd& v2)->bool{return v1 < v2}
类是有用的,因为据我所知,只要定义了std::less
,它就可以生成lambda函数。
但是,我发现operator<
对我不起作用,例如,下面的代码运行正常:
std::less<VectorXd>
但是,如果我像这样使用#include "Eigen/Dense"
#include <iostream>
#include <functional>
using namespace std;
using namespace Eigen;
struct T
{
int x;
};
bool operator<(const T& t1, const T& t2)
{
return t1.x < t2.x;
}
bool operator<(const VectorXd& v1, const VectorXd& v2)
{
return (v1.array() <= v2.array()).all() and (v1 != v2);
}
int main()
{
T t1, t2;
t1.x = 3;
t2.x = 2;
auto ft = std::less<T>();
cout << ft(t1, t2) << endl;
return EXIT_SUCCESS;
}
:
std::less<VectorXd>
代码无法编译,我收到如下错误消息:
#include "Eigen/Dense"
#include <iostream>
#include <functional>
using namespace std;
using namespace Eigen;
struct T
{
int x;
};
bool operator<(const T& t1, const T& t2)
{
return t1.x < t2.x;
}
bool operator<(const VectorXd& v1, const VectorXd& v2)
{
return (v1.array() <= v2.array()).all() and (v1 != v2);
}
int main()
{
T t1, t2;
t1.x = 3;
t2.x = 2;
auto ft = std::less<T>();
cout << ft(t1, t2) << endl;
VectorXd v1(3);
VectorXd v2(3);
v1 << 1, 2, 3;
v2 << 2, 3, 4;
auto fv = std::less<VectorXd>();
cout << fv(v1, v2) << endl;
return EXIT_SUCCESS;
}
我正在使用g ++ 5.4.0和Eigen 3.3
答案 0 :(得分:9)
这就是事情。您的T
无法可靠地重新创建此情况。您省略了名称空间,这非常重要。 Eigen
案例的更接近的例子是:
namespace Foo {
struct T
{
int x;
};
}
bool operator<(const Foo::T& t1, const Foo::T& t2)
{
return t1.x < t2.x;
}
它会产生完全相同的错误。这是因为模板只会考虑在模板定义(而不是实例化)点找到的此运算符的重载,或者argument dependent lookup对操作数类型的重载。< / p>
要使参数依赖查找起作用,必须在同一名称空间中定义运算符和类型,而这显然不是。
所以会发生什么,包括functional
。这定义了翻译单元中的模板std::less
。那时,operator<
就没有Eigen::VectorXd
了。因此,模板定义在以后定义时不会考虑它。
当您实例化模板时,它会尝试在知道关闭的那些模块中查找合适的重载,然后通过ADL查找。由于operator<
不在Eigen
命名空间内,因此ADL也找不到它。
总而言之,对于库类型的运算符重载是不切实际的。你应该做的是定义一个自定义比较器类型:
struct VectorXdCompare {
bool operator()(const VectorXd& v1, const VectorXd& v2) {
return (v1.array() <= v2.array()).all() and (v1 != v2);
}
};
每当标准库需要时,将VectorXdCompare
作为类型传递。