Получение шаблонного типа производного элемента структуры вектора базового класса - PullRequest
0 голосов
/ 12 июня 2018

У меня есть вектор, который является std::unique_ptr моей базовой структуры TextElBaseParams.Элементы этого вектора состоят из структур, которые имеют шаблон TextElParams<T>, они получены из TextElBaseParams.Производная структура содержит указатель на переменную типа T с именем var.

. У меня есть функция, которая может принимать только TextElParams<T>.Я не могу передать элементы из вектора TextElBaseParams в эту функцию по понятным причинам, поэтому у меня есть идея, что я могу каким-то образом преобразовать эти элементы обратно в их «производный» тип перед передачей их в функцию.

Это правильный путь?Если это так, что будет самым простым способом реализовать это?Если нет, какие альтернативы я мог бы использовать для решения этой проблемы?

Я использую SFML, но единственное, что здесь нужно сделать, не имеет значения.Вот основная схема моего кода:

struct TextElBaseParams {

};

template <typename T> struct TextElParams : public TextElBaseParams {
     TextElParams( std::string _font = "",
                   std::string _str = "",
                   int _fontSize = 1,
                   sf::Vector2f _position = {0,0},
                   T *_var = nullptr ) :
                   font{_font}, str{_str}, fontSize{_fontSize},
                   position{_position}, var{_var} {}

    std::string font;
    std::string str;
    int fontSize;
    sf::Vector2f position;
    T *var;
};

Я пытаюсь вызвать функцию addElement, которая принимает аргумент TextElParams<T>:

std::vector<std::unique_ptr<TextElBaseParams>> tParamsVec; //Filled with derived elements

for(unsigned int i=0; i<tParamsVec.size(); ++i)
        addElement(*tParamsVec.at(i));

Прототип для addElementфункция:

template<class T>
void addElement(TextElParams<T> &tParams);

addElement работает, если вы напрямую передаете ему TextElParams<T> struct.

1 Ответ

0 голосов
/ 13 июня 2018

Вот для чего нужны виртуальные функции.Создайте виртуальную функцию в базовом классе и переопределите ее в производных классах.Теперь, если вы вызываете функцию через указатель на базовый класс, вызывается соответствующая производная функция.См. Пример:

class Base {
public:
    virtual void invoke() = 0;
    virtual ~Base() {}
};

template<typename T>
class Derived;

template<typename T>
void func(Derived<T>& arg) {
    std::cerr << "called func with type " << typeid(T).name() << std::endl;
    // do smth with arg
}

template<typename T>
class Derived : public Base {
public:
    void invoke() override {
        func(*this);
    }
};

int main() {
    std::vector<std::unique_ptr<Base>> vec;

    vec.push_back(std::make_unique<Derived<int>>());
    vec.push_back(std::make_unique<Derived<double>>());
    vec.push_back(std::make_unique<Derived<void>>());

    for (const auto& t: vec) {
        t->invoke();
    }
}

Вывод:

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