我经常使用类型擦除技术。 它通常看起来像这样:
class YetAnotherTypeErasure
{
public:
// interface redirected to pImpl
private:
// Adapting function
template ...
friend YetAnotherTypeErasure make_YetAnotherTypeErasure (...);
class Interface {...};
template <typename Adaptee>
class Concrete final : public Interface {
// redirecting Interface to Adaptee
};
std::unique_ptr<Interface> pImpl_; // always on the heap
};
std::function
做了类似的事情,但它有一个小的缓冲区优化,所以如果Concrete<Adaptee>
小于smth并且没有抛出移动操作,它将被存储在其中。是否有一些通用的库解决方案可以相当容易地做到这一点?为了强制只在编译时存储小缓冲区?也许已经提出了一些标准化建议?
我对标准或任何提案所要求的小缓冲区优化一无所知,尽管它经常被允许或鼓励。
请注意,此类类型的一些(有条件的)非抛出要求实际上需要在实践中进行优化,因为替代方案(例如来自紧急缓冲区的非抛出分配)在这里似乎很疯狂。另一方面,您可以基于标准库(例如
std::aligned_storage
)从头开始制作自己的解决方案。从用户的角度来看,这可能仍然很冗长,但并不太难。
实际上我几年前就实现了(当时没有提出)any
这样的优化
和一些相关的实用程序。最近,libstdc++ 的
std::experimental::any
实现使用了几乎与此完全相同的技术(但是,__
前缀的内部名称对于普通库用户来说肯定不好)。我的实现现在使用一些常见的助手来处理存储。这些助手确实可以轻松实现类型擦除存储策略(至少适合类似于any
的东西)。但我仍然对更通用的高级解决方案感兴趣,以简化界面重定向。
function
实现
直接基于上面的
any
实现。它们支持仅移动类型和合理的分配器接口,而 std
则不支持。在某些情况下,由于底层 function
对象的(部分无操作)默认初始化,std::function
实现比 libstdc++ 中的 any
具有更好的性能。