使用Type-Erasure创建运行时type_traits查询

时间:2012-08-10 16:27:03

标签: c++ templates type-erasure

是否可以使用Type Erasure创建封装任意类型的对象(让我们称之为ErasedType),并且可以在运行时查询以判断是否有另一个任意类型T可转换为ErasedType

在考虑之后,我认为这是不可能的 - 即使它似乎在理论上可能可能。编译器会知道我们尝试与T比较哪些类型ErasedType,因此可以在运行时生成必要的代码。问题是,在实践中,似乎没有 ANY 方式将模板参数类型从Base类实例传递给Subclass实例。

例如:

struct FooBase
{
    template <class TestType>
    bool is_convertible()
    {
        return call_derived();
    }

    protected:

    virtual bool call_derived() = 0;

    template <class ErasedType>
    void base_class_function() { }
};

template <class ErasedType>
struct Foo : public FooBase
{
    bool call_derived()
    {
        // Here we have access to the ErasedType but no access to TestType.
            //
        // We could pass ErasedType to a base class function by saying:
        //
        // this->base_class_function<ErasedType>();
        //
        // ...but that doesn't seem to help since we still don't have access to
        // TestType
    }
};



因此,目标是能够说出类似的内容:

FooBase* f = new Foo<int>();
bool res1 = f->is_convertible<double>(); // returns true
bool res2 = f->is_convertible<long>(); // returns true
bool res3 = f->is_convertible<std::string>(); // returns false

但是,我无法看到FooBase::is_convertible方法是如何实现的,因为我认为无法在同一个函数中同时访问TestTypeErasedType,所以编译器可以计算std::is_convertible<TestType, ErasedType>::value

的结果

那么,这一切都可能吗?

1 个答案:

答案 0 :(得分:2)

在C ++中确实不可能,一般。在运行时对类型进行任意查询需要相当多的元数据,C ++会尽量保持最小化(有时候会有点烦人;一个功能可能会在“使用中”自动选择加入,所以没有不必要的开销,但我反对)。

正如大卫所暗示的那样,完全有可能将编译器信息复制到一定程度,但永远不会完全自动复制。这会将运行时类型信息限制为您手动添加的信息。

看一下像Qt这样的库,它们在C ++之上有一个完整的框架来提供这个元数据,看看涉及哪种工作。根据手头的问题,你可以在没有它的情况下过关。