【发布时间】:2015-11-02 19:47:05
【问题描述】:
最近,我遇到了几个使用“手动”vtable 的类型擦除实现 - Adobe ASL's any_regular_t 就是一个例子,尽管我也看到它在 Boost ASIO 中使用过(为了完成例行队列)。
基本上,父类型被传递一个指向静态类型的指针,该静态类型充满了子类型中定义的函数指针,类似于下面...
struct parent_t;
struct vtbl {
void (*invoke)(parent_t *, std::ostream &);
};
struct parent_t {
vtbl *vt;
parent_t(vtbl *v) : vt(v) { }
void invoke(std::ostream &os) {
vt->invoke(this, os);
}
};
template<typename T>
struct child_t : parent_t {
child_t(T val) : parent_t(&vt_), value_(val) { }
void invoke(std::ostream &os) {
// Actual implementation here
...
}
private:
static void invoke_impl(parent_t *p, std::ostream &os) {
static_cast<child_t *>(p)->invoke(os);
}
T value_;
static vtbl vt_;
};
template<typename T>
vtbl child_t<T>::vt_ = { &child_t::invoke_impl };
我的问题是,这个成语有什么好处?据我所知,这只是对编译器免费提供的内容的重新实现。当parent_t::invoke 调用vtbl::invoke 时,是否还会有额外间接的开销。
我猜这可能与编译器能够内联或优化对 vtbl::invoke 的调用有关,但我对 Assembler 无法解决这个问题感到不舒服我自己。
【问题讨论】:
-
在实现 C 对象时需要它(不使用 C++ 对象)
-
@DieterLücking 你的意思是便携性?它似乎在仅限 C++ 的库中也很流行
-
另一个原因:通过(诚然不平凡的)修改,您可以创建一个虚函数调用 matrix 而不是简单的 vtable,以实现 multiple dispatch。它有点令人费解,但 Stroustrup 与人合着了一系列论文,概述了可能的实现。
-
在 C++ 中仅使用 C 功能允许您制作兼容的库,即使不存在 C++ ABI。 (您定义 ABI。)
标签: c++ type-erasure vtable