Jak przekazać wektor unique_ptr do funkcji?

0

Witam,

class Helper
{
public:
    Helper();
    template<typename T>
    void sortByName(const std::vector<T>& vector )
    {
        std::sort(vector.begin(), vector.end());
    }
};
using namespace std;

int main(int argc, char *argv[])
{
    {
    std::shared_ptr<Manager> manager = std::make_shared<Manager>();
    std::unique_ptr<Model> model1 = std::make_unique<Model>("1",18, manager);
    std::unique_ptr<Model> model2 = std::make_unique<Model>("2",25, manager);

    std::vector<std::unique_ptr<Model>> vec;
    vec.push_back(std::move(model1));
    vec.push_back(std::move(model2));
    Helper helper;
    helper.sortByName(std::move(vec)); // błąd
    }
    return 0;
}

Błąd:
use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Model; _Dp = std::default_delete<Model>``

Rozumiem, że nie można kopiować unique_ptr, nie rozumiem tylko jak to się tutaj odbywa. Będę wdzięczny za wytłumaczenie.

1

sortByName przyjmuje const referencję do wektora. Tego nie da rady posortować, bo nie możesz takiego wektora modyfikować.

1
void sortByName(const std::vector<T>& vector )

std::sort modyfikuje kontener, więc przekazywanie jako const & na pewno nie przejdzie.

helper.sortByName(std::move(vec));

Jaki jest sens wołania move() na vec? W ten sposób właśnie mówisz, że po tej linii już nie będziesz się odwołać do zmiennej vec, bo oddałeś jej zasoby funkcji sortByName.

Podsumowując:

void sortByName(std::vector<T>& vector)
...
helper.sortByName(vec);
0

Dzięki, lecę dalej z koksem :-) Chciałbym, żeby moja klasa Helper umożliwiała sortowanie różnych klas na różne sposoby. Np. zarówno klasa Manager jak i klasa Model mają pola imie. Chciałbym to sortować alfabetycznie. Chciałbym również sortować np. po cenie lub wypłacie.
Jakie jest tutaj najlepsze, generyczne podejście? Takie, żebym mógł później tej klasy używać właśnie do różnych typów klas.

0

Nie bardzo rozumiem sensu istnienia funkcji/klasy, której jedyne zadanie jest wołanie std::sort().

0

No to albo będziesz tworzył metody sortujące o znaczących nazwach albo przekażesz komparator w postaci funkcji porównującej. 1 podejście tworzy dość duży interfejs. W drugim możesz np. definiować metodę domyślnego sortowania.
Tu masz przykład samo-opisujących się reguł oraz możliwość użycia lambdy "z palca". Standard C+14 bo użyłem gdzieniegdzie auto.

#include <vector>
#include <algorithm>
#include <string>
#include <functional>

class People {
public:
    // Dla przykładu wystarczy agregat..
    std::string name;
    std::string surname;
    unsigned age;
};

struct CompareBy {
    bool name(People& p1, People& p2) {
        return p1.name < p2.name;
    }
    bool surname(People& p1, People& p2) {
        return p1.surname < p2.surname;
    }
    bool age(People& p1, People& p2) {
        return p1.age < p2.age;
    }
};

int main() {
    std::vector<People> peoples = {
        {"Adam", "Smith", 21}, {"Frank", "Zappa", 53},
        {"Mireq", "Kovalsky", 53}
    };

    using std::placeholders::_1;
    using std::placeholders::_2;

    // Sortujemy.. 
    CompareBy comp;
    std::sort(peoples.begin(), peoples.end(),
            std::bind(&CompareBy::name, &comp, _1, _2));
    // Podobnie dla CompareBy::surname i age

    // Jakieś nietypowe sortowanie.. 
    std::sort(peoples.begin(), peoples.end(), [](auto& p1, auto& p2) {
        return (p1.age - 10) > p2.age;
    });
        
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1