在编译时捕获std::函数分配

catch std::function allocations at compile time

本文关键字:函数 分配 std 编译      更新时间:2023-10-16

我想只允许在我的代码库中使用std::function,如果它不做任何分配。

为此,我可以编写类似下面的函数,并且只使用它来创建我的函数实例:

template< typename Functor>
std::function<Functor> makeFunction( Functor f)
{
    return std::function<Functor>(std::allocator_arg, DummyAllocator(), f);
}

如果DummyAllocator在运行时被使用,它将断言或抛出。

理想情况下,我希望在编译时捕获分配用例。

template< typename Functor>
std::function<Functor> makeFunction( Functor f)
{
   static_assert( size needed for function to wrap f < space available in function, 
   "error - function will need to allocate memory");
   return std::function<Functor>(f);
 }

这样的事情可能吗?

您拥有的工厂方法可能是您最好的选择。

如果不合适,您可以选择为function实现适配器;使用std::function作为成员变量实现接口,以便适配器执行约束。

template <typename S>
class my_function {
  std::function<S> func_;
public:
  template <typename F>
  my_function(F&& f) :
  func_(std::allocator_arg, DummyAllocator(), std::forward<F>(f))
  {}
  // remaining functions required include operator()(...)
};

我会写一个不分配的std::function替代品,因为std::function会在需要时分配内存,这里有一个候选。

给定库中支持std::function分配器,只需为std::function提供一个不能工作的分配器。

template< typename t >
struct non_allocator : std::allocator< t > {
    t * allocate( std::size_t n ) { throw std::bad_alloc{}; }
    void deallocate( t * ) {}
    non_allocator() = default;
    template< typename u >
    non_allocator( non_allocator< u > const & ) {}
    template< typename u >
    struct rebind { typedef non_allocator< u > other; };
};
template< typename t, typename u >
bool operator == ( non_allocator< t > const &, non_allocator< t > const & )
    { return true; }
template< typename t, typename u >
bool operator != ( non_allocator< t > const &, non_allocator< t > const & )
    { return false; }

不幸的是,这在GCC中不起作用,因为它甚至没有为function声明任何allocator_arg构造函数。即使在Clang中,编译时错误也是不可能的,因为它不幸地使用运行时if对常量值来决定是否使用分配器。