2014-03-13 66 views
1

我認爲容器必須重新分配給他們的分配器,但是在帶有LLVM(我猜是libC++的一部分)的STL中,似乎並不是這種情況。這是LLVM中的錯誤,還是標準不需要重新綁定?是否使用C++標準所要求的allocator :: rebind?

下面的代碼片段與GCC的STL一樣按預期工作。它伴隨着3.3版的STL(來自Mac上的MacPorts)而失敗。它在Linux上用clang編譯得很好,但我認爲它使用與GCC相同的STL。

#include <vector> 

int main() 
{ 
    std::vector<char, std::allocator<int> > c; 
    c.push_back(5); 
} 

的錯誤是

clang++ test-rebind.cpp 
In file included from test-rebind.cpp:1: 
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/vector:505:5: error: implicit instantiation of undefined template '__static_assert_test<false>' 
    static_assert((is_same<typename allocator_type::value_type, value_type>::value), 
    ^
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/__config:412:35: note: expanded from macro 'static_assert' 
    typedef __static_assert_check<sizeof(__static_assert_test<(__b)>)> \ 
           ^
test-rebind.cpp:5:46: note: in instantiation of template class 'std::__1::vector<char, std::__1::allocator<int> >' requested here 
    std::vector<char, std::allocator<int> > c; 
              ^
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/__config:408:24: note: template is declared here 
template <bool> struct __static_assert_test; 
        ^
1 error generated. 
+0

_Hm,這是一個迴應已被刪除的評論,但我會留下回應,只是case._嗯,重新分配器修復問題。我認爲容器應該在內部自動完成它(這就是GCC的STL所做的)。我對此的手動修復是重新綁定每個容器的所有(自定義)分配器。這是乏味的,但它的工作原理。 – foxcub

+0

該評論已被刪除,因爲我注意到我誤解了您的代碼段。 –

回答

4

23.2.1 [container.requirements.general]/7:

所有其他的構造爲這些容器類型採取Allocator&參數(17.6.3.5),分配器,其值類型是相同容器的值類型。

所以你的代碼無效。

雖然上面是一個相當晦澀的地方找到這個。我們可以做得更好。表99(分配器識別的容器要求)在其第一行中要求容器具有allocator_type嵌套類型,其value_type與容器的相同。和用於vector上述梗概(和其它容器)限定allocator_type從而:

typedef Allocator allocator_type; 

換句話說,你提供Allocator參數是負責實現的要求。

+0

含義GCC曾經過於寬鬆,LLVM的STL是否正確執行規則? – foxcub

+3

正確,libstdC++過於寬鬆,而libC++包含明確的靜態斷言,該要求得到遵守。 –

+0

libstdC++檢查啓用概念檢查的需求,但不檢查 –

3

我以爲容器具有重新綁定給他們成工作

我找不到任何地方,要求一個分配器什麼分配器。相反,如果容器需要分配而不是value_type,則使用rebind。考慮一個典型的,簡化的list實現:

template <typename T, typename A = std::allocator<T>> 
class list { 
    struct node { 
     T value; 
     node* next; 
     node* prev; 
    }; 
    using allocator = typename A::template rebind<node>::other; 
}; 

在這裏,我們需要使用rebind因爲list不分配T秒;它分配list<T>::node s。

相關問題