Reputation: 791
I want to only allow use of std::function in my code base if it does not do any allocations.
To this end I can write something like the function below and only use it to create my function instances:
template< typename Functor>
std::function<Functor> makeFunction( Functor f)
{
return std::function<Functor>(std::allocator_arg, DummyAllocator(), f);
}
where DummyAllocator will assert or throw if it ever gets used at runtime.
Ideally though I would like to catch allocating use cases at compile time.
i.e.
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);
}
Is something like this possible?
Upvotes: 7
Views: 766
Reputation: 30614
The factory method you have is probably your best bet.
If not suitable, you may choose to implement an adaptor for function
; implement the interface with the std::function
as a member variable such that the adaptor enforces your constraints.
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()(...)
};
Upvotes: 2
Reputation: 14603
I'd write a std::function
replacement that does not allocate, as std::function
does allocate memory if it needs to, here's one candidate.
Upvotes: 2
Reputation: 137900
Given std::function
allocator support in your library, simply provide std::function
with an allocator that doesn't work.
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; }
Unfortunately, this doesn't work in GCC because it does not even declare any allocator_arg
constructors for function
. Even in Clang, a compile-time error is impossible because it unfortunately uses a runtime if
on a constant value to decide whether or not to use the allocator.
Upvotes: 0