-1

I'm trying to find the min element as follows:

#include <algorithm>
#include <iostream>
#include <vector>

#include <Eigen/Dense>

using namespace std;

template<typename T>
bool isLeftOf(const Eigen::Vector2<T>& a,
              const Eigen::Vector2<T>& b) {
  return (a.x() < b.x() || (a.x() == b.x() && a.y() < b.y()));
}

int main(int argc, char *argv[])
{
  std::vector<Eigen::Vector2<float> > points;
  points.push_back(Eigen::Vector2<float>(-1, -1));
  points.push_back(Eigen::Vector2<float>(1, -1));
  points.push_back(Eigen::Vector2<float>(0.5, 0));
  points.push_back(Eigen::Vector2<float>(1, 1));
  points.push_back(Eigen::Vector2<float>(0, 1.5));
  points.push_back(Eigen::Vector2<float>(-1, 1));
  points.push_back(Eigen::Vector2<float>(-0.7, 0));

  Eigen::Vector2<float> outpointa = min_element(*points.begin(),
                                                *points.end(), isLeftOf<float>);

return 0;
}

But I get compiler error:

...\algorithm(9199): error C2675: unary '++': '_FwdIt' does not define this operator or a conversion to a type acceptable to the predefined operator with [ _FwdIt=Eigen::Matrix<float,2,1,0,2,1> ]

How to overcome this?

Kerim
  • 171
  • 3
  • 10
  • 1
    `std::min_element` accepts a range of iterators. What's with the `*` there? – milleniumbug Jan 02 '21 at 13:52
  • 1
    `*points.begin(), *points.end()` -> `points.begin(), points.end()` && `min_element` -> `*min_element`. `xxx.begin()` is an iterator. Dereferencing that iterator (by using `*`) gives you the elements. Standard algorithms do not want elements. They want iterators or ranges. – Fureeish Jan 02 '21 at 13:52
  • @milleniumbug, @Fureeish actually without `*` I get an errors: main.cxx:103:25: errors: no viable conversion from 'std::_Vector_iterator>>>' to 'Eigen::Vector2' (aka 'Matrix') Matrix.h:273:5: note: candidate constructor not viable: no known conversion from 'std::_Vector_iterator – Kerim Jan 02 '21 at 14:34
  • 1
    Do yourself a favor: This is a case where the keyword `auto` is your friend: `auto outpointa = min_element(points.begin(), points.end(), isLeftOf);` -- If you have a good enough C++ based editor, you will see what that `auto` actually is. – PaulMcKenzie Jan 02 '21 at 14:52
  • Thank you Paul. Compiler gives me the following type: `std::_Vector_iterator>>>`. It is too complicated... Could it be somehow simplified? – Kerim Jan 02 '21 at 14:58
  • The return value of `std::min_element` is an iterator, not the actual value. To get the value, you need to dereference the iterator. So simply: `auto outpointa = *min_element(points.begin(), points.end(), isLeftOf);` -- Now check what `auto` gives you. – PaulMcKenzie Jan 02 '21 at 15:03
  • Thank you Paul! Now I can see that the output is `Eigen::Vector2`. If you (or anybody who wrote comments above) summirize this information as an answer (not a comment) I will accept it – Kerim Jan 02 '21 at 15:14

1 Answers1

1

you need to provide iterators to min_element

this will do , no need to dereference the iterators.


Eigen::Vector2<float> outpointa = min_element(points.begin(),
                                                points.end(), isLeftOf<float>);
User
  • 572
  • 2
  • 10
  • If I remove `*` then I can't assign the result of the expression to `Eigen::Vector2 outpointa`. I get errors mentioned above in comments – Kerim Jan 02 '21 at 14:39
  • use auto outpointa = min_element(*points.begin(), *points.end(), isLeftOf); – User Jan 02 '21 at 14:54