为什么std :: less <eigen :: vectorxd>无法编译?

时间:2017-10-18 13:51:59

标签: c++ eigen eigen3

我为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

1 个答案:

答案 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作为类型传递。