2015-08-27 45 views
5

我想只允许在我的代码库中使用std :: function(如果它没有做任何分配)。在编译时catch 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); 
} 

是这样的可能吗?

+3

我不认为Small Object Optimization暴露在'std :: function'中,依赖它会导致无法移植的代码。例如。 libC++使用一个大小为3'void *'的缓冲区,这在32位和64位x86系统上是不同的。 libC++使用'sizeof(__ buf_)'来检查是否应该使用SOO,并且我无法找到任何暴露此信息的函数。 – dyp

+0

@dyp那么,代码本身是可移植的。它将在所有平台上编译并产生预期结果。如果这个想法只允许使用不分配std :: function,不管怎样(我可以看到一些合理的场景调用这个),这是明智的做法。在编译时捕获分配是不可能的,因为它们不会在编译时发生。 – SergeyA

+0

@SergeyA如果ctor的剩余代码是constexpr,那么你可以在编译时捕获它们,但这对于SOO是不可能的,因为它必须使用placement-new。我对可移植性的评论更多的是试图解释为什么它没有被暴露。即使'int x = 1 << 17;'也是不可移植的代码,我当然同意OP中的不可移植性是最好的(编译器错误)。 – dyp

回答

2

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

如果不合适,您可以选择使用适配器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()(...) 
}; 
0

鉴于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; } 

不幸的是,这并不在海湾合作委员会的工作,因为它甚至不声明任何allocator_arg构造函数function。即使在Clang中,编译时错误也是不可能的,因为它不幸地使用运行时的if来决定是否使用分配器。

2

我会写一个std::function替换,不分配,因为std::function确实分配内存,如果需要的话,这里是一个candidate