Использование лямбда-функции для изменения класса - PullRequest
0 голосов
/ 04 июня 2019

В настоящее время я пытаюсь использовать std::transform() для вектора, который содержит интеллектуальные указатели на класс с именем Triangle, в котором у меня есть несколько методов, которые изменяют Triangle параметры.

Теперь я хочусделать мою жизнь проще и использовать std::transform() с моей собственной лямбда-функцией и применять ее к каждому динамически размещаемому треугольнику.

Однако я столкнулся с проблемой при попытке доступа к закрытым атрибутам моего класса внутри этой самой лямбда-функции,Мне любопытно, как я могу преодолеть эту проблему?

typedef std::pair<double, double> Point;

//the class Triangle contains these methods:

class Triangle{
    Point t1, t2, t3;
public:
    Trougao(const Point &t1, const Point &t2, const Point &t3){
        if(Triangle::Orijentacija(t1,t2,t3)==0) 
            throw std::domain_error("Incorrect vertices");
        Triangle::t1.first=t1.first;
        Triangle::t1.second=t1.second;
        Triangle::t2.first=t2.first;
        Triangle::t2.second=t2.second;
        Triangle::t3.first=t3.first;
        Triangle::t3.second=t3.second;
    }

    void Set(const Point &t1, const Point &t2, const Point &t3){
        if(Triangle::Orientation(t1,t2,t3)==0)
            throw std::domain_error("Incorrect vertices");
        Triangle::t1.first=t1.first;
        Triangle::t1.second=t1.second;
        Triangle::t2.first=t2.first;
        Triangle::t2.second=t2.second;
        Triangle::t3.first=t3.first;
        Triangle::t3.second=t3.second;
    }

    void Set(int indeks, const Point &t){
        if(indeks!=1 && indeks!=2 && indeks!=3)
            throw std::range_error("Incorrect index");
        if(indeks==1){
            this->t1.first=t.first;
            this->t1.second=t.second;
        }
        else if(indeks==2){
            this->t2.first=t.first;
            this->t2.second=t.second;
        }
        else if (indeks==3){
            this->t3.first=t.first;
            this->t3.second=t.second;
        }
    }

    Point GiveVertex(int indeks) const{
        if(indeks!=1 && indeks!=2 && indeks!=3)
            throw std::range_error("Incorrect index");
        if(indeks==1) return Triangle::t1;
        else if(indeks==2) return Triangle::t2;
        else if(indeks==3) return Triangle::t3;
    }

    void Translate(double delta_x, double delta_y){
        t1.first+=delta_x;
        t1.second+=delta_y;
        t2.first+=delta_x;
        t2.second+=delta_y;
        t3.first+=delta_x;
        t3.second+=delta_y;
    }
};

//now I would like to make in my main program a vector of smart pointers 
//which I would use do dyn. alloc. "n" Triangles. After that I want to use 
//std::transform to Translate every single one (with lambda function)
//I am currently stuck at implementation of this lambda function as you can 
// see:
//-------------(main)------------------------------
int main()
{
    std::cout<<"How many triangles: ";
    std::cin>>n;
    std::vector<double> translation_vector(2);
    double angle, scale_faktor;
    Point dot1, dot2, dot3; 
    std::vector<std::shared_ptr<Triangle>> vect_smrt_ptr(n);
    for(int i(0); i<n; i++){
        std::cout<<"Input data for the"<<i+1<<". triangle (x1 y1 x2 y2 x3 y3):";
        std::cin>>dot1.first>>dot1.second>>dot2.first>>dot2.second>>dot3.first>>dot3.second;
        std::shared_ptr<Triangle> smrt_ptr(new Triangle(dot1, dot2, dot3));
        vect_smrt_ptr.at(i)=smrt_ptr;
    }
    std::cout<<"Input translation vector (dx dy): ";
    std::cin>>translation_vector.at(0)>>translation_vector.at(1);

    //now the tricky part!
    std::transform(&vect_smrt_ptr.at(0), &vect_smrt_ptr.at(vect_smrt_ptr.size()), &vect_smrt_ptr.at(0),
        [translation_vector](Triangle tr){ tr.Translate(translation_vector.at(0), translation_vector.at(1)); }
    );

1 Ответ

0 голосов
/ 04 июня 2019

std::transform не является хорошим выбором в вашем случае, потому что он должен конвертировать одну коллекцию объектов в другую коллекцию (конечно, в конкретном случае, выходная коллекция может совпадать с входной коллекцией).Например:

std::transform(inputCollection.begin(), inputCollection.end(), outputCollection.begin(),
    [](YourClass obj) {
        YourClass modified = ApllySomeModification(obj);
        return modified;
    });

В вашем случае std::for_each - лучший алгоритм:

std::for_each(vect_smrt_ptr.begin(), vect_smrt_ptr.end(),
    [translation_vector](std::shared_ptr<Triangle> tr) {
        tr->Translate(translation_vector.at(0), translation_vector.at(1));
    });

, потому что он имеет семантику изменения ваших элементов на месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...