C++ Stateful функтор, который заполняет векторы
У меня вопрос по поводу функторов. Я построил простой класс:
class PolygonPrinter {
private:
std::vector<float> x;
std::vector<float> y;
public:
inline void operator()(Point& p) {
x.push_back(boost::geometry::get<0>(p));
y.push_back(boost::geometry::get<1>(p));
}
void printPoints() {
for(int i=0; i < x.size(); i++) {
std::cout << "("
<< x[i] << "," << y[i]
<< ")" << std::endl;
}
}
}
Который я хотел использовать в качестве функтора. Это используется в чем-то вроде
PolygonPrinter<point_2d> polyPrinter;
boost::geometry::for_each_point( polygon, polyPrinter );
polyPrinter.printPoints();
Теперь кажется, что часть функтора работает нормально, так как я вижу, что векторы заполняются всеми элементами многоугольника (поэтому for_each_point работает как положено), однако третий вызов ( printPoints) не печатает точек, и фактически оба вектора пусты. Я предполагаю, что такое поведение ожидается, однако я не могу понять, как очищаются векторы. Я думал, что вы могли бы иметь функторы с состоянием.
Если бы кто-то мог объяснить, почему векторные поля x и y в экземпляре polyPrinter пусты, это было бы здорово.
ура
2 ответа
std
алгоритмы копируют ваш функтор. boost
вероятно, делает то же самое.
Вы можете std::ref( functor )
передать его через псевдо-ссылку, и вы получите поведение, которое вы хотите.
boost::geometry::for_each_point( polygon, std::ref(polyPrinter) );
Кроме того, ваше использование inline
избыточно: все методы, определенные в теле класса, неявно inline
, Это источник веселья для отслеживания ошибок.
Это не тот же случай PolygonPrinter
,
Определение от Boost API:
template<typename Geometry, typename Functor>
Functor for_each_point(Geometry & geometry, Functor f)
Функтор передается копией! Таким образом, вы фактически создаете новый экземпляр для Boost API для работы, и, следовательно, он не влияет на ваш экземпляр. Если вы хотите захватить новое состояние (после использования for_each_point
) используйте возвращаемое значение, чтобы переназначить ваш экземпляр с одним возвратом Boost. Конечно, это предполагает, что ваш конструктор копирования делает то, что вы ожидаете: копирует нужные значения каким-то образом. В вашем конкретном случае у вас есть конструктор копирования по умолчанию, поэтому он должен работать как положено.
PolygonPrinter<point_2d> polyPrinter;
polyPrinter = boost::geometry::for_each_point( polygon, polyPrinter );
polyPrinter.printPoints();