стирание типа c ++ / инкапсуляция типа? открыть тип - PullRequest
2 голосов
/ 28 февраля 2012

Я, вероятно, совершенно не согласен с этим, но я из c #, поэтому заранее прошу прощения.

Сначала немного о том, что я пытаюсь сделать.У меня есть базовый класс фабрики, определенный в моем коде как

template<typename _Ty>
class Factory
{
public:
    virtual std::shared_ptr<_Ty> Create() = 0;
};

. То, что я хочу сделать, - это иметь список фабрик (скажем, вектор или список stl) и затем искать их потип шаблона.До сих пор я понял, что мне нужен вектор или список какого-либо содержащего типа, поэтому я придумал:

class FactoryContainer
{
    struct FactoryConcept {
        virtual ~FactoryConcept() {}
    };

    template< typename _Ty > struct FactoryModel : FactoryConcept {
        FactoryModel( const _Ty& t ) : factory( t ) {}
        virtual ~FactoryModel() {}
    private:
        _Ty factory;
    };
    std::shared_ptr<FactoryConcept> factory;

public:
    template< typename _Ty > FactoryContainer( const _Ty& _factory ) :
        factory( new FactoryModel<_Ty>( _factory ) ) {}
};

Я бы хотел включить какой-то метод в контейнер, чтобысравните тип, что-то вроде

template<typename _Ty> bool isType(){...}

, но у меня есть нет идеи, как это реализовать, или я даже на правильном пути с определением типа после использования типаerasure.

РЕДАКТИРОВАТЬ: После нескольких комментариев о том, что это проблема XY, я решил еще раз подчеркнуть, что я делаю (о чем я говорил).

Я хочу иметь stlКонтейнер типа Factory (включая любые и все созданные экземпляры типов шаблонов) и сможет извлечь один из типов шаблона.Для меня лучший способ I сделать это (а это может быть лучший способ ) - это использовать класс контейнера, инкапсулирующий тип, и иметь возможность отвечать, если содержитсяТип является фактическим с использованием предоставленного типа шаблона.Если это не так, то сдавайся.Я не могу использовать dynamic_cast как предложено, поскольку в то время, когда я пытаюсь это выяснить, у меня нет указателя ни на один из типов.Я сейчас смотрю на typeid и надеюсь, что это решит мои проблемы, но я все еще жду другого возможного ответа.

РЕДАКТИРОВАТЬ 2: После игры с несколькими ответами я не нашел ничего, что вполне соответствуетмои требованияВот краткие требования:

шаблон базового класса:

template<typename FactoryType>
class Factory
{
public:
    virtual std::shared_ptr<FactoryType> Create() = 0;
    virtual ~Factory(){}
};

класс менеджера фабрики:

class Manager
{
    static std::shared_ptr<Manager> singleton;
public:
    static std::shared_ptr<Manager> getInstance()
    {
        if (!singleton) singleton = shared_ptr<Manager>(new Manager);
        return singleton;
    }
    template<typename FactoryType>
    Factory<FactoryType>& getFactory()
    {
        //Pick a factory here by the type and return it by reference
        //life cycle is handled by the manager
    }
};

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

Ответы [ 2 ]

4 голосов
/ 28 февраля 2012

Ну, так как вы используете C ++ 11, вы можете хранить std::type_index объектов.

Вы получаете их с помощью оператора typeid: typeid возвращает const std::type_info&, но type_info не подходит для использования, например. в качестве ключей карт. Таким образом, вы создаете объект std::type_index для этой цели. Фактическое решение зависит от вас.

Что-то вроде

std::map<std::type_index, std::shared_ptr<factory>>
Например,

подойдет (замените shared_ptr на правильный тип указателя для вашего дизайна).

Обратите внимание, что в C ++ вы стараетесь избегать информации о типах времени выполнения. Если вы покажете, чего пытаетесь достичь, мы могли бы попытаться найти лучшее решение.


EDIT

При условии сравнения std::type_info объектов на равенство работает через границы DLL (поскольку это требование, см. Ваш комментарий), вы можете реализовать его следующим образом:

class FactoryContainer
{
    struct FactoryConcept {
        virtual ~FactoryConcept() {}
        virtual const std::type_info& Type() const;
    };

    template< typename _Ty > struct FactoryModel : FactoryConcept {
        FactoryModel( const _Ty& t ) : factory( t ) {}
        virtual ~FactoryModel() {}
    private:
        _Ty factory;
        const std::type_info& Type() const { return typeid(_Ty); }
    };
    std::shared_ptr<FactoryConcept> factory;

public:
    template< typename _Ty > FactoryContainer( const _Ty& _factory ) :
        factory( new FactoryModel<_Ty>( _factory ) ) {}

    template <typename T>
    bool hasType() const { return factory->Type() == typeid(T); }
};

Использование:

bool result = container.hasType<double>();
0 голосов
/ 28 февраля 2012

Это уже существует.Он называется dynamic_cast<T*>(ptr) и возвращает значение true, если ptr указывает на T или любой класс, производный от T, предполагая, что статический тип *ptr и T оба имеют по крайней мереодна виртуальная функция.

Вы также можете использовать typeid() и связанных друзей для поиска информации о типах во время выполнения.

...