使用类型擦除创建运行时type_traits查询

Using Type-Erasure to create runtime type_traits queries

本文关键字:type traits 查询 运行时 创建 类型 擦除      更新时间:2023-10-16
是否可以

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

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

例如:

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的结果

那么,这可能吗?

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

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

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