Почему std :: less не удается скомпилировать?

Я Eigen::VectorXd оператор operator< сравнения operator< для Eigen::VectorXd , а иногда мне нужно передать функцию сравнения другой функции, я устал обматывать operator< в [](const VectorXd& v1, const VectorXd& v2)->bool{return v1 < v2} , поэтому я думаю, что class std::less будет полезен, так как, насколько я понимаю, он может генерировать lambda-функцию, если operator< определен.

Однако я обнаружил, что std::less не работает для меня, например, нижеследующий код работает нормально:

 #include "Eigen/Dense" #include  #include  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(); cout << ft(t1, t2) << endl; return EXIT_SUCCESS; } 

Однако, если я использую std::less следующим образом:

 #include "Eigen/Dense" #include  #include  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(); cout << ft(t1, t2) << endl; VectorXd v1(3); VectorXd v2(3); v1 << 1, 2, 3; v2 << 2, 3, 4; auto fv = std::less(); cout << fv(v1, v2) << endl; return EXIT_SUCCESS; } 

Код не компилируется, и я получаю сообщения об ошибках, как показано ниже:

 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::operator()(const _Tp&, const _Tp&) const [with _Tp = Eigen::Matrix]': 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' and 'const Eigen::Matrix') { 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 constexpr bool std::operator<(const std::pair&, const std::pair&) operator<(const pair& __x, const pair& __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' is not derived from 'const std::pair' { 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 bool std::operator<(const std::reverse_iterator&, const std::reverse_iterator&) operator<(const reverse_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' is not derived from 'const std::reverse_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 bool std::operator<(const std::reverse_iterator&, const std::reverse_iterator&) operator<(const reverse_iterator& __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' is not derived from 'const std::reverse_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 bool std::operator<(const std::move_iterator&, const std::move_iterator&) operator<(const move_iterator& __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' is not derived from 'const std::move_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 bool std::operator<(const std::move_iterator&, const std::move_iterator&) operator<(const move_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' is not derived from 'const std::move_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 bool std::operator<(const std::__cxx11::basic_string&, const std::__cxx11::basic_string&) operator<(const basic_string& __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' is not derived from 'const std::__cxx11::basic_string' { 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 bool std::operator<(const std::__cxx11::basic_string&, const _CharT*) operator<(const basic_string& __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' is not derived from 'const std::__cxx11::basic_string' { 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 bool std::operator<(const _CharT*, const std::__cxx11::basic_string&) 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' { 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' 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' 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 bool std::operator<(const std::array&, const std::array&) operator<(const array& __a, const array& __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' is not derived from 'const std::array' { 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 constexpr bool std::operator<(const std::tuple&, const std::tuple&) operator<(const tuple& __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' is not derived from 'const std::tuple' { 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 bool std::operator<(const std::vector&, const std::vector&) operator<(const vector& __x, const vector& __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' is not derived from 'const std::vector' { return __x < __y; } ^ make: *** [try] Error 1 

Я использую g ++ 5.4.0 и Eigen 3.3

Вот что. Ваш T не воссоздает ситуацию надежно. Вы пропустили пространство имен, что очень важно. Более близким примером для случая с Eigen будет следующее:

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

И это приведет к той же ошибке. Это связано с тем, что шаблон учитывает только перегрузки этого оператора, которые находятся в точке определения шаблона (а не инстанцирования), или зависимым от аргументов поисками типов операндов.

А для зависимого от аргументов поиска для работы оператор и тип должны быть определены в одном и том же пространстве имен, что, очевидно, не так.

Итак, что происходит, вы включаете 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 как тип, когда нужна стандартная библиотека.