2015-08-27 18 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