Эквивалент instanceof / extends в C ++ - PullRequest
0 голосов
/ 20 июня 2020

Я хочу создать диспетчер ресурсов, и у меня есть представление о том, как он должен работать, но я не могу понять, как настроить его соответствующим образом в C ++

class Resource{
public:
    virtual void loadFromFile();
};

class Texture: public Resource{
public:
    void loadFromFile(){ do texture specific loading }
};

class Mesh: public Resource{
public:
    void loadFromFile(){ do mesh specific loading }
};

class ResourceManager{
private:
    vector<Resource*> resources;
public:
    template <typename T>
    void addResource(){
        T* resource = new T;
        resource->loadFromFile();
        resources.push_back(resource);
    }
};

Как я могу обеспечить соблюдение этого T расширяет Resource и не является ли классом, у которого есть метод с таким же именем?

Ответы [ 2 ]

2 голосов
/ 20 июня 2020

Чтобы получить приятное дружественное сообщение об ошибке, вы можете использовать static_assert:

#include <type_traits>

template <typename T>
void addResource(){
    static_assert (std::is_base_of_v<Resource, T>, "T must derive from Resource");
    ...

. Это вызовет ошибку во время компиляции, если T не выводится с Resource.

0 голосов
/ 20 июня 2020

Так как вектор resources имеет тип Resource*, если вы попытаетесь вставить что-то, что не является производным от Resource, вы получите ошибку времени компиляции.

В противном случае вы можете SFINAE:

class ResourceManager{
private:
    std::vector<Resource*> resources;
public:
    template <typename T>
    std::enable_if_t<std::is_base_of_v<Resource, T>, void> addResource(){
        T* resource = new T;
        resource->loadFromFile();
        resources.push_back(resource);
    }
}

Используйте SFINAE, только если вы хотите сделать что-то еще, если T не является производным от Resource, в противном случае вы можете полностью положиться на ошибку времени компиляции на resources.push_back(pointer)

РЕДАКТИРОВАТЬ: Фактически вы можете заставить T быть производным от Resource, используя систему типов:

void addResource(){
    Respurce* resource = new T;
    resource->loadFromFile();
    resources.push_back(resource);
}

Но только если loadFromFile объявлен в Resource, а не в T (т. ваш пример будет работать) (Спасибо @ RemyLebeau)

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