c ++类型擦除/类型封装?发现类型

时间:2012-02-28 17:19:42

标签: c++ templates type-erasure

我可能完全偏离此基础,但我来自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(){...}

但是我没有想法如何实现它,或者我甚至在使用类型擦除后确定类型的正确轨道上。

编辑: 在多次评论这是一个XY问题后,我决定重新强调我正在做的事情(我说过了)。

我希望有一个类型为Factory的stl容器(包括任何和所有实例化的模板类型),并且能够从模板类型中选择一个。对我来说,看到这样做的最佳方式(可能不是最好的方式)是使用类型封装容器类,并让它能够响应包含的类型实际上是使用提供的模板类型。如果不是,那就放弃吧。我无法按照建议使用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来了解。在编译管理器时,将不知道工厂的可能类型,并且它由彼此不了解的代码引用。有可能并且很可能在这里装载了我不知道并且不知道的工厂,因为许多工厂都是由其他人制造并放入dll。

2 个答案:

答案 0 :(得分:4)

好吧,既然您正在使用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 ++中,您会尽量避免运行时类型信息。如果你揭露了你想要实现的目标,我们可以尝试找到更好的解决方案。


修改

提供了比较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>();

答案 1 :(得分:0)

那已经存在。它被称为dynamic_cast<T*>(ptr),如果ptr指向T或从T派生的任何类,则返回true,假设{em> static 类型为{{ 1}}和*ptr都至少有一个虚函数。

您还可以使用T及相关朋友在运行时发现有关类型的信息。