为任意类型擦除实现小缓冲区优化的简单方法(如在std :: function中)。

时间:2015-11-07 12:31:28

标签: c++ c++11

我倾向于使用类型擦除技术。 它通常看起来像这样:

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并且没有进行移动操作,它将被存储在其中。是否有一些通用的库解决方案来做到这一点相当容易?为了强制只在编译时存储的小缓冲区?也许已经提出了标准化的建议?

3 个答案:

答案 0 :(得分:3)

我对标准或任何提案所要求的所需的小缓冲区一无所知,但通常允许或鼓励它。

另一方面,您可以基于标准库(例如std::aligned_storage)从头开始制作自己的解决方案。这可能仍然从用户的角度来看,但不是太难。

实际上,几年前我实施了(不建议)any with such optimizationsome related utilities。最近,libstdc ++的std::experimental::any实现几乎完全采用了这种技术(但__前缀内部名称肯定不适合普通的库用户。)

我的实现现在使用some common helpers来处理存储。这些帮助程序很容易实现类型擦除存储策略(至少适合类似于any的类似)。但我仍然对更简单的高级解决方案感兴趣,以简化界面重定向。

答案 1 :(得分:0)

我认为C ++ 20 polymorphic_value最接近我们在现代c ++中可以做到的:wg21.link/p0201

基本上就像std :: any一样,但是所有类型都必须继承相同的接口。 这是半规则的,他们决定放弃平等。

这有一些开销:类本身中的一个vptr和多态值中的单独的调度机制。它也有一个像接口这样的指针,而不是像这样的值。

但是,考虑到与编写自己的type_erased适配器相比使用起来很容易,我想对于大多数用例来说已经足够了。

答案 2 :(得分:0)

我为日常代码找到了一个不错的解决方案-使用std :: function

借助微小的库支持以帮助const正确性, 代码减少到20行: https://gcc.godbolt.org/z/GtewFI