[llvm-bugs] [Bug 37694] New: std::vector does not satisfy container.requirements.general clause 8
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Jun 5 13:45:19 PDT 2018
https://bugs.llvm.org/show_bug.cgi?id=37694
Bug ID: 37694
Summary: std::vector does not satisfy
container.requirements.general clause 8
Product: libc++
Version: 6.0
Hardware: PC
OS: All
Status: NEW
Severity: normal
Priority: P
Component: All Bugs
Assignee: unassignedclangbugs at nondot.org
Reporter: sdconsta at syr.edu
CC: llvm-bugs at lists.llvm.org, mclow.lists at gmail.com
Clause 23.2.1.8 of n4140 states that for containers which obtain memory using
an allocator, "Move constructors obtain an allocator by move construction from
the allocator belonging to the container being copied." This requirements does
not hold for std::vector:
#include <memory>
#include <forward_list>
#include <vector>
#include <map>
#include <iostream>
template <typename T>
class my_allocator {
std::allocator<T> __alloc;
public:
using value_type = T;
using propagate_on_container_move_assignment = std::true_type;
my_allocator() = default;
my_allocator(const my_allocator &other) : __alloc(other.__alloc) {
std::cout << "copy constructor\n";
}
my_allocator(my_allocator &&other) noexcept : __alloc(other.__alloc) {
std::cout << "move constructor\n";
}
value_type *allocate(std::size_t n) {
return __alloc.allocate(n);
}
void deallocate(value_type *p, std::size_t n) {
__alloc.deallocate(p, n);
}
};
int main() {
std::forward_list<int, my_allocator<int>> l = {1, 2, 3, 4};
auto l1 = std::move(l);
std::map<int, int, std::less<int>, my_allocator<std::pair<const int, int>>> m
= {{1, 2}, {3, 4}};
auto m1 = std::move(m);
std::vector<int, my_allocator<int>> v = {1, 2, 3, 4};
auto v1 = std::move(v);
}
(compiled only with -std=c++14 on clang++) prints:
move constructor
move constructor
copy constructor
If we instead delete the copy constructor, clang emits
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/memory:2097:9: error: call to
deleted constructor of 'my_allocator<int>'
: __value_(_VSTD::forward<_Up>(__u)){};
^ ~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/memory:2197:42: note: in
instantiation of function template specialization
'std::__1::__compressed_pair_elem<my_allocator<int>, 1,
false>::__compressed_pair_elem<const my_allocator<int> &, void>'
requested here
: _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {}
^
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/vector:432:7: note: in
instantiation of function template specialization
'std::__1::__compressed_pair<int *, my_allocator<int>
>::__compressed_pair<nullptr_t, const my_allocator<int> &>' requested
here
__end_cap_(nullptr, __a)
^
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/vector:1242:7: note: in
instantiation of member function 'std::__1::__vector_base<int,
my_allocator<int> >::__vector_base' requested here
: __base(_VSTD::move(__x.__alloc()))
^
test.cpp:35:13: note: in instantiation of member function
'std::__1::vector<int, my_allocator<int> >::vector' requested here
auto v1 = std::move(v);
^
test.cpp:15:3: note: 'my_allocator' has been explicitly marked deleted here
my_allocator(const my_allocator &) = delete;
^
1 error generated.
I believe the problem is that there is no constructor for __vector_base which
accepts an rvalue reference to the allocator. Hence the copy constructor is
being called instead.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180605/76f4d9d9/attachment.html>
More information about the llvm-bugs
mailing list