是否可以使用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
方法是如何实现的,因为我认为无法在同一个函数中同时访问TestType
和ErasedType
,所以编译器可以计算std::is_convertible<TestType, ErasedType>::value
那么,这一切都可能吗?
答案 0 :(得分:2)
在C ++中确实不可能,一般。在运行时对类型进行任意查询需要相当多的元数据,C ++会尽量保持最小化(有时候会有点烦人;一个功能可能会在“使用中”自动选择加入,所以没有不必要的开销,但我反对)。
正如大卫所暗示的那样,完全有可能将编译器信息复制到一定程度,但永远不会完全自动复制。这会将运行时类型信息限制为您手动添加的信息。
看一下像Qt这样的库,它们在C ++之上有一个完整的框架来提供这个元数据,看看涉及哪种工作。根据手头的问题,你可以在没有它的情况下过关。