使用分配器::C++标准所需的重新绑定?

使用分配器::C++标准所需的重新绑定?,c++,stl,allocator,C++,Stl,Allocator,我认为容器必须将给定的任何分配器重新绑定到一个有效的分配器中,但在libc++的LLVM部分附带的STL中,我想情况似乎并非如此。这是LLVM中的一个bug,还是该标准不需要重新绑定 下面的代码片段与GCC的STL的预期效果相同。在Mac上,MacPorts的Clang3.3附带了STL,但它失败了。它在Linux上使用clang可以很好地编译,但我认为它使用的STL与GCC相同 #include <vector> int main() { std::vector<c

我认为容器必须将给定的任何分配器重新绑定到一个有效的分配器中,但在libc++的LLVM部分附带的STL中,我想情况似乎并非如此。这是LLVM中的一个bug,还是该标准不需要重新绑定

下面的代码片段与GCC的STL的预期效果相同。在Mac上,MacPorts的Clang3.3附带了STL,但它失败了。它在Linux上使用clang可以很好地编译,但我认为它使用的STL与GCC相同

#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.
我认为容器必须将给定的任何分配器重新绑定到一个有效的分配器中

我到处都找不到那个要求。相反,如果容器需要分配值类型以外的内容,则使用重新绑定。考虑一个典型的、简化的列表实现:

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;
};
这里我们需要使用重新绑定,因为列表不分配Ts;它分配list::nodes

我认为容器必须将给定的任何分配器重新绑定到一个有效的分配器中

我到处都找不到那个要求。相反,如果容器需要分配值类型以外的内容,则使用重新绑定。考虑一个典型的、简化的列表实现:

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

这里我们需要使用重新绑定,因为列表不分配Ts;它分配列表::节点。

<23.2.1[容器.要求.常规]/7:

这些容器类型的所有其他构造函数都采用分配器&参数17.6.3.5,该分配器的值类型与容器的值类型相同

所以你的代码是无效的

不过,在上面这一点上,我们还不太清楚。我们可以做得更好。表99支持分配器的容器要求在其第一行中要求容器具有分配器类型嵌套类型,其值类型与容器的值类型相同。vector和其他容器的概要定义了分配器类型:


换句话说,您提供的分配器参数负责满足要求。

23.2.1[container.requirements.general]/7:

这些容器类型的所有其他构造函数都采用分配器&参数17.6.3.5,该分配器的值类型与容器的值类型相同

所以你的代码是无效的

不过,在上面这一点上,我们还不太清楚。我们可以做得更好。表99支持分配器的容器要求在其第一行中要求容器具有分配器类型嵌套类型,其值类型与容器的值类型相同。vector和其他容器的概要定义了分配器类型:


换句话说,您提供的分配器参数负责满足要求。

Hm,这是响应的注释已被删除,但我将保留响应,以防万一。嗯,重新绑定分配器可以解决问题。我认为容器应该在内部自动完成,这就是GCC的STL如何完成的。我的手动修复方法是为每个容器重新绑定所有自定义分配器。这很枯燥,但很有效。注释被删除了,因为我注意到我误读了你的代码片段。嗯,这是回复的注释被删除了,但我会留下回复,以防万一。嗯,重新绑定分配器可以解决问题。我认为容器应该在内部自动完成,这就是GCC的STL如何完成的。我的手动修复方法是为每个容器重新绑定所有自定义分配器。这很枯燥,但很有效。注释被删除了,因为我注意到我误读了您的代码段。这意味着GCC过去过于宽松,LLVM的STL正确地执行了规则?正确,libstdc++过于宽松,而libc++包含一个明确的静态断言,表示该需求已得到遵守。libstdc++在启用概念检查的情况下检查该需求,但并不意味着GCC过去过于宽松,而LLVM的STL正确地执行了该规则?正确,libstdc++过于宽松,而libc++包含一个明确的静态断言,表示该需求已得到遵守。libstdc++在启用概念检查的情况下检查该需求,但在其他情况下不进行检查