Why can't std :: less <Eigen :: VectorXd> compile?

I implemented the operator operator comparison operator< for Eigen::VectorXd , and sometimes I need to pass the comparison function to another function, I'm tired of wrapping operator< in [](const VectorXd& v1, const VectorXd& v2)->bool{return v1 < v2} , so I think std::less would be useful since, as far as I understand, it can generate a lambda function until operator< defined.

However, I found that std::less<VectorXd> does not work for me, for example, the following code works fine:

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

However, if I use std::less<VectorXd> as follows:

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

The code fails to compile, and I get error messages as shown below:

 In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h: In instantiation of 'bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Eigen::Matrix<double, -1, 1>]': test.cpp:36:26: required from here /usr/include/c++/5/bits/stl_function.h:387:20: error: no match for 'operator<' (operand types are 'const Eigen::Matrix<double, -1, 1>' and 'const Eigen::Matrix<double, -1, 1>') { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/stl_algobase.h:64:0, from /usr/include/c++/5/bits/char_traits.h:39, from /usr/include/c++/5/ios:40, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_pair.h:220:5: note: candidate: template<class _T1, class _T2> constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) ^ /usr/include/c++/5/bits/stl_pair.h:220:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::pair<_T1, _T2>' { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/stl_algobase.h:67:0, from /usr/include/c++/5/bits/char_traits.h:39, from /usr/include/c++/5/ios:40, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_iterator.h:298:5: note: candidate: template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&) operator<(const reverse_iterator<_Iterator>& __x, ^ /usr/include/c++/5/bits/stl_iterator.h:298:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::reverse_iterator<_Iterator>' { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/stl_algobase.h:67:0, from /usr/include/c++/5/bits/char_traits.h:39, from /usr/include/c++/5/ios:40, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_iterator.h:348:5: note: candidate: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_IteratorR>&) operator<(const reverse_iterator<_IteratorL>& __x, ^ /usr/include/c++/5/bits/stl_iterator.h:348:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::reverse_iterator<_Iterator>' { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/stl_algobase.h:67:0, from /usr/include/c++/5/bits/char_traits.h:39, from /usr/include/c++/5/ios:40, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_iterator.h:1089:5: note: candidate: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::move_iterator<_Iterator>&, const std::move_iterator<_IteratorR>&) operator<(const move_iterator<_IteratorL>& __x, ^ /usr/include/c++/5/bits/stl_iterator.h:1089:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::move_iterator<_Iterator>' { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/stl_algobase.h:67:0, from /usr/include/c++/5/bits/char_traits.h:39, from /usr/include/c++/5/ios:40, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_iterator.h:1095:5: note: candidate: template<class _Iterator> bool std::operator<(const std::move_iterator<_Iterator>&, const std::move_iterator<_Iterator>&) operator<(const move_iterator<_Iterator>& __x, ^ /usr/include/c++/5/bits/stl_iterator.h:1095:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::move_iterator<_Iterator>' { return __x < __y; } ^ In file included from /usr/include/c++/5/string:52:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/basic_string.h:4987:5: note: candidate: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, ^ /usr/include/c++/5/bits/basic_string.h:4987:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>' { return __x < __y; } ^ In file included from /usr/include/c++/5/string:52:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/basic_string.h:4999:5: note: candidate: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _CharT*) operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, ^ /usr/include/c++/5/bits/basic_string.h:4999:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>' { return __x < __y; } ^ In file included from /usr/include/c++/5/string:52:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/basic_string.h:5011:5: note: candidate: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) operator<(const _CharT* __lhs, ^ /usr/include/c++/5/bits/basic_string.h:5011:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: mismatched types 'const _CharT*' and 'Eigen::Matrix<double, -1, 1>' { return __x < __y; } ^ In file included from /usr/include/c++/5/bits/ios_base.h:46:0, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/system_error:200:3: note: candidate: bool std::operator<(const std::error_code&, const std::error_code&) operator<(const error_code& __lhs, const error_code& __rhs) noexcept ^ /usr/include/c++/5/system_error:200:3: note: no known conversion for argument 1 from 'const Eigen::Matrix<double, -1, 1>' to 'const std::error_code&' /usr/include/c++/5/system_error:274:3: note: candidate: bool std::operator<(const std::error_condition&, const std::error_condition&) operator<(const error_condition& __lhs, ^ /usr/include/c++/5/system_error:274:3: note: no known conversion for argument 1 from 'const Eigen::Matrix<double, -1, 1>' to 'const std::error_condition&' In file included from /usr/include/c++/5/tuple:39:0, from /usr/include/c++/5/functional:55, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:262, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/array:250:5: note: candidate: template<class _Tp, long unsigned int _Nm> bool std::operator<(const std::array<_Tp, _Nm>&, const std::array<_Tp, _Nm>&) operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) ^ /usr/include/c++/5/array:250:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::array<_Tp, _Nm>' { return __x < __y; } ^ In file included from /usr/include/c++/5/functional:55:0, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:262, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/tuple:928:5: note: candidate: template<class ... _TElements, class ... _UElements> constexpr bool std::operator<(const std::tuple<_Elements ...>&, const std::tuple<_Elements ...>&) operator<(const tuple<_TElements...>& __t, ^ /usr/include/c++/5/tuple:928:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::tuple<_Elements ...>' { return __x < __y; } ^ In file included from /usr/include/c++/5/vector:64:0, from /usr/include/c++/5/bits/random.h:34, from /usr/include/c++/5/random:49, from /usr/include/c++/5/bits/stl_algo.h:66, from /usr/include/c++/5/algorithm:62, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:269, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_vector.h:1528:5: note: candidate: template<class _Tp, class _Alloc> bool std::operator<(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&) operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) ^ /usr/include/c++/5/bits/stl_vector.h:1528:5: note: template argument deduction/substitution failed: In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/istream:38, from /usr/include/c++/5/sstream:38, from /usr/include/c++/5/complex:45, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Core:80, from /home/alaya/.softwares/linear_algebra/eigen3.3/include/eigen3/Eigen/Dense:1, from test.cpp:1: /usr/include/c++/5/bits/stl_function.h:387:20: note: 'const Eigen::Matrix<double, -1, 1>' is not derived from 'const std::vector<_Tp, _Alloc>' { return __x < __y; } ^ make: *** [try] Error 1 

I am using g ++ 5.4.0 and Eigen 3.3

+7
c ++ eigen eigen3
source share
1 answer

Here is the thing. Your T does not allow you to reliably recreate the situation. You missed the namespace, which is very important. A closer example for the Eigen case would be:

 namespace Foo { struct T { int x; }; } bool operator<(const Foo::T& t1, const Foo::T& t2) { return t1.x < t2.x; } 

And that will lead to the same error. This is due to the fact that the template takes into account only overloads of this operator that are at the point of the template definition (rather than instantiation), or an argument-dependent search for operand types.

And for a search-dependent argument to work, the operator and type must be defined in the same namespace, which yours clearly doesn't match.

So what happens is you turn on functional . This defines the std::less pattern in your translation unit. At that time there was no operator< for Eigen::VectorXd . Therefore, the definition of a template will not take it into account when it is defined later.

When you instantiate the template, it tries to find a suitable overload among those who knew this, and then ADL. Since your operator< not in the Eigen namespace, it is also not found by ADL.

In short, it is impractical to overload statements for library types. What you have to do is define your own type of comparator:

 struct VectorXdCompare { bool operator()(const VectorXd& v1, const VectorXd& v2) { return (v1.array() <= v2.array()).all() and (v1 != v2); } }; 

And pass this VectorXdCompare as a type when you need a standard library.

+9
source share

All Articles