-
Notifications
You must be signed in to change notification settings - Fork 772
[vector.capacity] p14 The precondition use "and" but should use "or" #5776
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
Comments
I think it's "and" because when |
But, in other words, when |
Moreover, consider this example std::vector<A> vec{};
vec.reserve(2);
std::cout<< vec.capacity()<<std::endl; // #1
vec.resize(10); // #2
|
From the comment of the implementation of |
When you do run out of capacity, you need the former set of requirements. Maybe what you want is to make the precondition of that set conditional. But I don't think that's editorial. |
See my last comment above. I'm not sure whether the implementation didn't obey the requirement, or whether there are some inconsistencies in the standard. At least, according to your opinion, the requirement |
The comment doesn't follow the standard terminology, but IIUC the actual implementation is right here. In that case, the libstdc++ implementation is actually default-inserting new elements (with We can't simply make Cpp17MoveInsertable or Cpp17DefaultInsertable conditional, because "Mandates" is missing here, and the well-formedness requirements, in my opinion, inappropriately appear in "Preconditions". I think there are several possible defects.
Anyway, I don't think this is editorial either. LWG issues seem needed. |
Yes, but simply changing the preconditions from "and" to "or" would not help that problem and would be totally wrong. That would imply that resizing when capacity is exceeded has to work for an object that can only be default constructed, but not copied or moved. That's nonsense. When shrinking the vector, neither Cpp17MoveInsertable nor Cpp17DefaultInsertable is required. When growing within the current capacity, only Cpp17DefaultInsertable is required. When exceeding the capacity, both are required. So the current wording is correct. In general, for an arbitrary call to So there is no editorial issue here, and any change to those requirements would be very non-editorial. |
At the time, there was a deliberate decision to not alter those requirements in Mandating the Standard Library: |
The wording "and" requires both conditions are true, I think. However, the condition |
This is not an issue of standard wording or implementations (at this moment). Using such non-Cpp17MoveInsertable |
i.e. the wording is correct. There is no editorial issue here. |
My original option is
AFAIK, the implementations of GCC and MSVC regarding |
Implementations are conforming here IIUC, as currently they are not required to reject non-Cpp17MoveInsertable types. The standard wording seemly has defects - copy insertion is suggested by the standard and conditionally used by all mainstream implementations (when the move construction is potentially throwing and copy construction is available), but the "Preconditions:" is only mentioning Cpp17MoveInsertable. This is not limited to
Yes. But libc++ rejects non-(formally-)Cpp17MoveInsertable types when conditional move-or-copy-insertion is used. (Note that Clang can be used together with libc++, libstdc++, and MSVC STL.) |
Which is one possible outcome of UB. I'm closing this, there is no editorial issue here. |
From certain perspectives, you're right to say implementations are conforming here. Since the violation of precondition results in UB, which means the document imposes no requirement. Implementations are free to do anything here. Since the behaviors of all mainstream implementations are similar, so I think we might expel the behavior from UB. |
@jwakely @JohelEGP @frederick-vs-ja struct T{
T() = default;
T(T&){} // suppress the implicitly-declared move constructor, and cannot take a rvalue as the argument
};
int main(){
std::vector<T> vec;
vec.resize(1024); // UB here since `T` is not Cpp17MoveInsertable
}; Using |
No, that type is Cpp17MoveInsertable into Edit: Oh wait, you've edited the code. I was replying to the original that said |
This issues list is not the right place to learn how vector works. |
As stated above, libc++ has a static assert. So not the same. |
The modified example was my original thought when wrote the comment. I'm not learning how to use vector, I just want to say the use of T that causes UB is widely used in actually code. |
No, because you can't use that type at all with |
I don't think this is true at all. Type with |
You're right, this is my oversight. However, the first example is indeed usable in actual code. Such as deep copy an object instead of using shallow copy. |
Deleting a move constructor is perverse. If you don't want it to be efficiently movable, just don't define a move constructor. Then you get deep copies of rvalues. Getting undefined behaviour for such types is fine, they're irregular and unnecessary. |
[vector.capacity] p14 says
Cpp17MoveInsertable is defined in [containers.container.alloc.reqmts] p2.3
[containers.container.alloc.reqmts] p2 says
Consider this example:
However,
A
is not Cpp17MoveInsertable sinceallocator_traits<A>::construct(m, p, RV)
is ill-formed forA
.The text was updated successfully, but these errors were encountered: