Skip to content
This repository has been archived by the owner. It is now read-only.

std::vector incorrectly requires CopyConstructible, Destructible and other concepts #28412

Closed
jwakely mannequin opened this issue Jul 4, 2016 · 4 comments
Closed

std::vector incorrectly requires CopyConstructible, Destructible and other concepts #28412

jwakely mannequin opened this issue Jul 4, 2016 · 4 comments
Assignees

Comments

@jwakely
Copy link
Mannequin

@jwakely jwakely mannequin commented Jul 4, 2016

Bugzilla Link 28412
Resolution FIXED
Resolved on Feb 11, 2019 15:56
Version unspecified
OS All
CC @hfinkel,@mclow,@tstellar

Extended Description

Container requirements are all stated in terms of CopyInsertable into X, and Erasable from X, which involves indirection through the container's allocator.

The following test shows a class which can only be constructed/destroyed by its allocator, revealing that std::vector tries to construct temporaries directly without going through the allocator.

/usr/local/libcxx-head/include/c++/v1/vector:1815:24: error: call to deleted constructor of 'value_type' (aka 'X')

#include

struct Tag { };

template
class TaggingAllocator
{
public:
using value_type = T;

TaggingAllocator() = default;

template<typename U>
  TaggingAllocator(const TaggingAllocator<U>&) { }

T*
allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }

void
deallocate(T* p, std::size_t n) { std::allocator<T>{}.deallocate(p, n); }

template<typename U, typename... Args>
  void
  construct(U* p, Args&&... args)
  { ::new((void*)p) U(Tag{}, std::forward<Args>(args)...); }

template<typename U, typename... Args>
  void
  destroy(U* p)
  { p->~U(); }

};

template<typename T, typename U>
bool
operator==(const TaggingAllocator&, const TaggingAllocator&)
{ return true; }

template<typename T, typename U>
bool
operator!=(const TaggingAllocator&, const TaggingAllocator&)
{ return false; }

struct X
{
// All constructors must be passed the Tag type.

// DefaultInsertable into vector<X, TaggingAllocator>,
X(Tag) { }
// CopyInsertable into vector<X, TaggingAllocator>,
X(Tag, const X&) { }
// MoveInsertable into vector<X, TaggingAllocator>, and
X(Tag, X&&) { }

// EmplaceConstructible into vector<X, TaggingAllocator> from args.
template<typename... Args>
X(Tag, Args&&...) { }

// not DefaultConstructible, CopyConstructible or MoveConstructible.
X() = delete;
X(const X&) = delete;
X(X&&) = delete;

// CopyAssignable.
X& operator=(const X&) { return *this; }

// MoveAssignable.
X& operator=(X&&) { return *this; }

private:
// Not Destructible.
~X() { }

// Erasable from vector<X, TaggingAllocator>.
friend class TaggingAllocator;
};

int main()
{
std::vector<X, TaggingAllocator> v;
v.reserve(3);
v.emplace_back();
v.emplace(v.begin());
v.emplace(v.begin(), 1, 2, 3);
}

// template class std::vector<X, TaggingAllocator>;

Uncommenting the last line to explicitly instantiate the vector fails differently, presumably there are some SFINAE conditions which make invalid assumptions about the type.

@jwakely
Copy link
Mannequin Author

@jwakely jwakely mannequin commented Jul 4, 2016

assigned to @mclow

Loading

@mclow
Copy link

@mclow mclow commented Jul 11, 2016

revision 275105 fixes this for deque and vector.
Leaving this open because I need to check the other containers.

Loading

@mclow
Copy link

@mclow mclow commented Jul 12, 2016

// template class std::vector<X, TaggingAllocator>;

Uncommenting the last line to explicitly instantiate the vector fails differently, presumably there are some SFINAE conditions which make invalid assumptions about the type.

The code that makes this blow up is in the SFINAE for assign:

X *p = new X(Tag());
v.assign(p, p + 1);

And this fails because is_constructible<X, X&>::value is false.

Loading

@mclow
Copy link

@mclow mclow commented Feb 11, 2019

This was fixed in revision 275105 (back on Jul 11 2016)

Loading

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant