在编译时捕获 std::function 分配
catch std::function allocations at compile time
我只想允许在我的代码库中使用 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);
}
这样的事情可能吗?
鉴于您的库中的 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
常量值来决定是否使用分配器。
我会写一个不分配的 std::function
替换,因为 std::function
会在需要时分配内存,这里是一个 candidate。
您拥有的工厂方法可能是您最好的选择。
如果不合适,您可以选择为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,如果它不进行任何分配的话。
为此,我可以编写类似下面的函数,并且只用它来创建我的函数实例:
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);
}
这样的事情可能吗?
鉴于您的库中的 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
常量值来决定是否使用分配器。
我会写一个不分配的 std::function
替换,因为 std::function
会在需要时分配内存,这里是一个 candidate。
您拥有的工厂方法可能是您最好的选择。
如果不合适,您可以选择为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()(...)
};