I implemented a comparison operator operator<
for Eigen::VectorXd
, and sometimes, I need to pass a compare function to another of my function, I am tired of wrapping the operator<
into [](const VectorXd& v1, const VectorXd& v2)->bool{return v1 < v2}
, so I think the std::less
class would be useful, as, to my understanding, it can generate the lambda function as long as operator<
is defined.
However, I found that std::less<VectorXd>
didn't work for me, for example, the below 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>
like this:
#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 like 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
Here's the thing. Your T
doesn't recreate the situation reliably. You omitted the namespace, which is very important. A closer example to the case with Eigen
would be this:
namespace Foo {
struct T
{
int x;
};
}
bool operator<(const Foo::T& t1, const Foo::T& t2)
{
return t1.x < t2.x;
}
And it will produce the exact same error. That is because a template will only consider overloads of this operator that are found at the point of the template definition (and not instantiation), or by argument dependent lookup on the types of the operands.
And for argument dependent lookup to work, the operator and the type must be defined in the same namespace, which yours clearly isn't.
So what happens is this, you include functional
. That defines the template std::less
in your translation unit. At that time, there is no operator<
for Eigen::VectorXd
in sight. So the template definition will not take it into consideration when it's defined later.
When you instantiate the template, it attempts to look for a suitable overload among those it was made aware off, and then by ADL. Since your operator<
is not inside the Eigen
namespace, it isn't found by ADL either.
So long story short, it's impractical to overload operators for library types. What you should do, is to define a custom comparator type:
struct VectorXdCompare {
bool operator()(const VectorXd& v1, const VectorXd& v2) {
return (v1.array() <= v2.array()).all() and (v1 != v2);
}
};
And pass that VectorXdCompare
as the type, whenever the standard library needs it.
来源:https://stackoverflow.com/questions/46811833/why-does-stdlesseigenvectorxd-fail-to-compile