5

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

仔细考虑之后,我认为这是不可能的——尽管它似乎在理论上是可能的编译器会知道T我们试图与哪些类型进行比较ErasedType,因此可以在运行前生成必要的代码。问题是,实际上,似乎没有任何方法可以将模板参数类型从基类实例传递到子类实例。

例如:

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

那么,这有可能吗?

4

1 回答 1

2

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

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

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

于 2012-08-10T19:06:03.320 回答