-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[libc++][NFC] Use __construct_at and __destroy_at instead of using preprocessor conditionals #70866
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM % CI.
71c9152
to
329af8f
Compare
3b8e283
to
c0735fe
Compare
@@ -16,5 +16,5 @@ | |||
|
|||
void f() { | |||
std::vector<MoveOnly> v; | |||
std::vector<MoveOnly> copy = v; // expected-error-re@* {{{{(no matching function for call to 'construct_at')|(call to implicitly-deleted copy constructor of 'MoveOnly')|(call to deleted constructor of 'MoveOnly')}}}} | |||
std::vector<MoveOnly> copy = v; // expected-error-re@* {{{{(no matching function for call to '__construct_at')|(call to implicitly-deleted copy constructor of 'MoveOnly')}}}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unfortunate that __construct_at
appears here, but I think that suggests we're testing too much of the compiler message.
A test should only fail when the behavior under test no longer holds. Is the name part of the behavior under test?
@@ -319,11 +315,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits | |||
__enable_if_t<!__has_destroy<allocator_type, _Tp*>::value> > | |||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 | |||
static void destroy(allocator_type&, _Tp* __p) { | |||
#if _LIBCPP_STD_VER >= 20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is using destroy_at
better than simply invoking the destructor? One costs a lot less to instantiate.
It's not a customization point, right?
@@ -300,11 +300,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits | |||
__enable_if_t<!__has_construct<allocator_type, _Tp*, _Args...>::value> > | |||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 | |||
static void construct(allocator_type&, _Tp* __p, _Args&&... __args) { | |||
#if _LIBCPP_STD_VER >= 20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as below.
Are we required to use construct_at
here? If not, it seems to be more expensive, and causes arguably poorer diagnostic messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for constexpr-friendliness IIRC.
c0735fe
to
a45da7e
Compare
You can test this locally with the following command:git-clang-format --diff 6bdeb53ed9ad85fc16f495120b4e2382c4bdaafa 18e2a699569190d4c360090d310dd4be7b02b770 -- libcxx/include/__memory/allocator_traits.h libcxx/include/optional libcxx/test/std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp libcxx/test/std/containers/sequences/vector/vector.modifiers/resize_not_move_insertable.verify.cpp View the diff from clang-format here.diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
index eea5ee973d..a2ce48b3fb 100644
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -300,7 +300,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
__enable_if_t<!__has_construct<allocator_type, _Tp*, _Args...>::value> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
static void construct(allocator_type&, _Tp* __p, _Args&&... __args) {
- std::__construct_at(__p, std::forward<_Args>(__args)...);
+ std::__construct_at(__p, std::forward<_Args>(__args)...);
}
template <class _Tp, class =
@@ -315,7 +315,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
__enable_if_t<!__has_destroy<allocator_type, _Tp*>::value> >
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
static void destroy(allocator_type&, _Tp* __p) {
- std::__destroy_at(__p);
+ std::__destroy_at(__p);
}
template <class _Ap = _Alloc, class =
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp
index af8ca01370..1179fde3f1 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/copy.move_only.verify.cpp
@@ -16,5 +16,6 @@
void f() {
std::vector<MoveOnly> v;
- std::vector<MoveOnly> copy = v; // expected-error-re@* {{{{(no matching function for call to '__construct_at')|(call to deleted constructor of 'MoveOnly')}}}}
+ std::vector<MoveOnly> copy =
+ v; // expected-error-re@* {{{{(no matching function for call to '__construct_at')|(call to deleted constructor of 'MoveOnly')}}}}
}
|
@EricWF This is essentially a small simplification of the code -- we have to use construct_at and destroy_at for constexpr-friendliness, and we also like to do it for consistency everywhere. So this really just trades |
…processor conditionals
a45da7e
to
18e2a69
Compare
What does "constexpr friendlyness" mean? Because it's just placement new. If this adds constexpr friendlyness then doesn't in need more tests? |
No description provided.