С++ функтор с состоянием, который заполняет векторы

У меня вопрос по функторам. Я построил простой класс:

    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 в экземпляре полипринтера пусты?


person A.I.    schedule 19.03.2015    source источник
comment
Я предполагаю, что ваш for_each_point получает копию оригинального полипринтера. Таким образом, копия заполняется точками, вы это видите, а оригинал по-прежнему пуст.   -  person Severin Pappadeux    schedule 19.03.2015


Ответы (2)


std алгоритмы копируют ваш функтор. boost, вероятно, делает то же самое.

Вы можете std::ref( functor ) передать его через псевдоссылку, и вы получите желаемое поведение.

boost::geometry::for_each_point( polygon, std::ref(polyPrinter) );

Кроме того, использование вами inline излишне: все методы, определенные в теле класса, неявно являются inline. Это источник некоторого удовольствия от отслеживания ошибок.

person Yakk - Adam Nevraumont    schedule 19.03.2015
comment
@alvini, если это решит вашу проблему, официальный способ отметить это как ответ — поставить галочку. Слева от него есть кнопка, которую нужно нажать. - person Yakk - Adam Nevraumont; 19.03.2015

Это не тот же экземпляр 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();
person Rollen    schedule 19.03.2015
comment
Я понял! Спасибо. Я должен был подумать об этом. - person A.I.; 19.03.2015