Передайте вектор базового класса функции, которая принимает вектор суперкласса

В моем коде у меня есть SuperType с двумя подтипами... теперь у меня есть std::vector<SubTypeA>& и мне нужно передать его функции, которая перебирает вектор и вызывает только функции из SuperType... Мне нужно сделать это с обоими подтипами.

(Супертип еще не виртуальный, но мне нужно сделать его виртуальным в какой-то момент, потому что это просто общая часть двух подтипов, и не может быть его экземпляра)

Вот минимальный (не)рабочий пример:

#include <vector>
struct Super {
    // stuff and functions
};
struct SubTypeA : public Super {
    // stuff and functions
};

void func(const std::vector<Super>& sup) {
    for (auto& elem: sup) {
        // do things
    }
    return;
}

int main() {
    std::vector<SubTypeA> v; // I get this from another place
    std::vector<SubTypeA>& my_variable = v; // this is what I have in my code
    func(my_variable); // does not work.
}

передача итератора тоже была бы решением.


Примечание: я получаю my_variable из другого типа:

struct SomeContainer {
    std::vector<SubTypeA> a;
    std::vector<SubTypeB> b;
}

И я бы не хотел менять контейнер, так что std::vector<SubTypeA>& он есть.


person musicmatze    schedule 08.11.2017    source источник
comment
std::vector<Super> отличается от std::vector<SubTypeA> и не может быть преобразован из одного в другой без потерь из-за нарезки объектов .   -  person Algirdas Preidžius    schedule 08.11.2017
comment
Возможный дубликат Как передать вектор класса Child в функцию, ожидающую вектор класса Parent?   -  person StaticBeagle    schedule 08.11.2017


Ответы (1)


В С++ ссылки и указатели типов Super и SubTypeA являются ковариантными, а std::vector<Super> и std::vector<SubTypeA> — нет. Вы можете использовать вектор указателей или ссылок на базовый класс для достижения желаемого:

#include <vector>
struct Super {
    // stuff and functions
};
struct SubTypeA : public Super {
    // stuff and functions
};

void func(std::vector<std::reference_wrapper<Super>>& sup) {
    for (Super& elem: sup) {
        // do things
    }
    return;
}

int main() {
    std::vector<SubTypeA> v; // I get this from another place
    // using vector of references to base class
    std::vector<std::reference_wrapper<Super>> my_variable(v.begin(), v.end());        

    func(my_variable); // does not work.
}

Обновлено в соответствии с рекомендациями в комментариях

person user2807083    schedule 08.11.2017
comment
Или вы можете сделать func шаблоном, который принимает итераторы начала/конца. - person Tamás Zahola; 08.11.2017
comment
std::vector имеет c'tor, который принимает пару итераторов. Использовать его будет короче, чем писать сырой цикл. - person StoryTeller - Unslander Monica; 08.11.2017
comment
Также std::reference_wrapper неявно преобразуется в ссылку. Так что, может быть, for (Super& ref: sup) снова пойти на лаконичность. - person StoryTeller - Unslander Monica; 08.11.2017