【问题标题】:Using Type-Erasure to create runtime type_traits queries使用 Type-Erasure 创建运行时 type_traits 查询
【发布时间】:2012-08-10 16:27:03
【问题描述】:

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

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

例如:

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&lt;TestType, ErasedType&gt;::value

那么,这可能吗?

【问题讨论】:

  • 您的类型擦除基类允许公开一个虚函数,该函数为您提供具体类型的type_id...但特征是一种编译时构造,不会真正与动态类型。
  • @KerrekSB: ...尽管您可以在运行时使用该信息构建查找结构...并在运行时查询。另一种选择是在类型擦除上伪造双重分派以通过“可转换”检查器......它们中的任何一个都需要相当多的样板代码并且不会完全通用。
  • @David,即使使用双重调度,每当您调用多态函数时,您仍然会丢失模板参数,所以您怎么能安排TestTypeErasedType 都是非隐藏的情况?
  • @Channel72:这就是为什么我评论说你需要大量的 boilerplate,与其他方法的不同之处在于你可以对擦除类型进行测试...如果有足够的时间,您可以根据特征类中的类型列表来实现这一点。评论的不完全通用部分是因为它只会选择您在该列表/查找中定义的转换。
  • 这里的(常见)问题是您想要关于类型的二次数据量(假设您无法访问编译器的内部线性数据量)但是虚拟/模板机制是有能力的只生成一个线性量(通过考虑每个类型参数仅在其自己的翻译单元中定义的情况可以看出)。

标签: c++ templates type-erasure


【解决方案1】:

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

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

看看像Qt 这样的库,它们在 C++ 之上有一个完整的框架来提供这个元数据,看看涉及到什么样的工作。根据手头的问题,您也许可以不用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2012-07-26
    • 1970-01-01
    相关资源
    最近更新 更多