类型擦除

在很多情况下,可能会有很多种不同的类型,但是他们都有着同样的一种函数,我们希望通过同一种类型来存储他,并统一调用这种“同样”的函数。

实际上这实际上就是一种没有虚的虚,因此我们可以通过类型擦除的方式来解决他。

例如我们有一些函数,都有operator()这个函数。

首先定义一个有“同样”函数的基类。

1
2
3
4
5
6
class functionImplBase {
public:
/// 里面为了完美转发可以&&
virtual void operator()() = 0;
virtual ~functionImplBase() = default;
};

然后再定义能够存储任何类型的派生类。

就能使用functionImplBase*存储任何类型。

1
2
3
4
5
6
7
8
template <typename F>
class functionImpl : public functionImplBase {
public:
explicit functionImpl(F&& f) : f(std::forward<F>(f)) {}
/// 当涉及到成员指针时,其调用非常特殊,因此必须使用std::invoke
void operator()() override { return f(); }
F f;
};

如果需要为其整体增加新的函数,可以直接定义函数重载,然后在派生类中直接调用这个函数。可以将这个函数放在一个namespace中不暴露出来。

而为了更加方便可以使用工厂,可以使用map来存储对应关系,然而,类型本身并不能作为map的成员,因此可以不存储类型而是存储类型的工厂。

而这一段的写法可以使用xmacro。

但类型擦除会损失性能,所以为了追求性能应该使用模板等非虚的方法。


类型擦除
https://lhish.github.io/project/hide/类型擦除/
作者
lhy
发布于
2025年8月16日
许可协议