Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

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

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

jwakely mannequin opened this issue Jul 4, 2016 · 4 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@jwakely
Copy link
Mannequin

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 mannequin commented Jul 4, 2016

assigned to @mclow

@mclow
Copy link
Contributor

mclow commented Jul 11, 2016

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

@mclow
Copy link
Contributor

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.

@mclow
Copy link
Contributor

mclow commented Feb 11, 2019

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

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

1 participant