P1144R0 "Object relocation in terms of move plus destroy" was presented to SG17 (EWGI) in San Diego. (Thanks to Corentin Jabot for trying to make it happen!) The paper lists the following straw polls that could have been taken. None of these polls were taken, and no feedback was given on the paper in San Diego.So I'd like to get your opinions! Please reply in this thread with your !votes on any or all of the following statements, in the traditional WG21 straw poll format: "Strongly For" the statement as written; "For" it; "Neutral" (as in, you considered the question and your expert opinion is that you are neutral on it — please do not use this option as a synonym for abstaining due to lack of an opinion); "Against" the statement as written; or "Strongly Against" it.The polls will remain open for one week, until Sunday 2018-11-18. If you don't want your !votes to be public, you can always email them to me privately.I will tally the ballots and report the results in P1144R1, which will appear in the post-San-Diego mailing (submission deadline: 2018-11-26).Here are the polls. Please vote in any or all of them, but only after reading the paper. When a poll says "...as proposed in this paper," it's referring to the formal wording from P1144R0. You would have to read that formal wording to know what's being asked!---------------------------------------EWG1. We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.
EWG2. We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members.
EWG3. Nobody should be able to warrant the trivial relocatability of class `C` except for class `C` itself (i.e., we do not want to see a customization point analogous to `std::hash`).
EWG4. A class should be able to warrant its own trivial relocatability via the attribute `[[trivially_relocatable]]`, as proposed in this paper.
EWG5. A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name.
EWG6. A class should be able to warrant its own trivial relocatability as proposed in this paper, but we prefer to see a contextual keyword rather than an attribute.
EWG7. If a trait with the semantics of `is_trivially_relocatable<T>` is added to the `<type_traits>` header, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to `std::hash`).
EWG8. Trivial relocatability should be assumed by default. Classes such as those in Appendix C should indicate their non-trivial relocatability via an opt-in mechanism.
EWG9. To simplify conditionally trivial relocation, if an attribute with the semantics of `[[trivially_relocatable]]` is added, it should take a boolean argument.
LEWG10. The algorithm `uninitialized_relocate(first, last, d_first)` should be added to the `<memory>` header, as proposed in this paper.
LEWG11. The type trait `is_relocatable<T>` should be added to the `<type_traits>` header, as proposed in this paper.
LEWG12. If `is_relocatable<T>` is added, then we should also add `is_nothrow_relocatable<T>`, as proposed in this paper.
LEWG13. The type trait `is_trivially_relocatable<T>` should be added to the `<type_traits>` header, under that exact name, as proposed in this paper.
LEWG14. We approve of a trait with the semantics of `is_trivially_relocatable<T>`, but possibly under a different name. (For example, `is_bitwise_relocatable`.)
LEWG15. If `is_trivially_relocatable<T>` is added, under that exact name, then the type trait `is_trivially_swappable<T>` should also be added to the `<type_traits>` header.
On 11/13/2018 10:25 AM, floria...@gmail.com wrote:
> Your class A cannot keep its invariants (p points to this, and pp points
> to p) across copy or move. So it's fine in that case to also break on
> relocation.
> For your class to be correct, you would need to write/disable copy and
> move constructors. In that case, rule of zero would not apply and
> relocability would not be inherited.
Right, that is not the good example. I still have a strong feeling that
R0 connects badly to this feature. The other direction looks more
obvious: just the presense of dtor looks completely irrelevant. Majority
of ctors handle different kinds of invariants.
I think I could construct one with virtual inheritance that uses no
user-defined ctors but has an embedded pointer.
As a general note this paper looks intimidatingly overcomplicated.
As a
programmer I'd welcome a SIMPLE facility, where I can opt in for
relocability, and the library accounts for that. no composition, no
automatics, no heuristics, UB if I lied -- and the whole paper would fit
on a single page with a poll just to bikeshed the syntax for opt-in.
A had the feeling like we are in two completely different
conversations... and that was the case indeed, I located the source.
All along I was talking about trivially relocatable (without pointing it
out, my bad). While the answers were provided in the general relocability.
This may provide some of the explanation of my previous claim on the
"overcomplicated". I just don't see any value from all those other
flavors. Neither from the top of my head nor from the paper. It provides
a good case for the trivial that I agree with and would like in the
language very much. As most of the types I work with are actually such.
And I do move them around in all kinds of operations not limited to
vector::push_back and sort.
What is the benefit of the other stuff? What cares for knowing a type is
nontrivially_throwing relocatable or nontrivially_nothrow_relocatable? I
mean as a separate, named concept, beyond its raw ingredients?
On Tuesday, November 13, 2018 at 7:47:33 PM UTC+2, Balog Pal wrote:A had the feeling like we are in two completely different
conversations... and that was the case indeed, I located the source.
All along I was talking about trivially relocatable (without pointing it
out, my bad). While the answers were provided in the general relocability.
This may provide some of the explanation of my previous claim on the
"overcomplicated". I just don't see any value from all those other
flavors. Neither from the top of my head nor from the paper. It provides
a good case for the trivial that I agree with and would like in the
language very much. As most of the types I work with are actually such.
And I do move them around in all kinds of operations not limited to
vector::push_back and sort.
What is the benefit of the other stuff?
What cares for knowing a type is
nontrivially_throwing relocatable or nontrivially_nothrow_relocatable? I
mean as a separate, named concept, beyond its raw ingredients?
If you know that, and believe it is significant benefit, you need to
emphasize that in the paper bigtime (while benefits of just doing a bulk
big memcpy instead of formal constructions and destructions are IMO
evident.)
Also providing a safe set of rules that can figure out
trivial_relocation for an aggregate/composite should be easier.
On 11/11/2018 20.35, Arthur O'Dwyer wrote:
> EWG3. Nobody should be able to warrant the trivial relocatability of class
> `C` except for class `C` itself (i.e., we do not want to see a
> customization point analogous to `std::hash`).
N leaning to A.
While this makes sense *in principle*, in practice it's not unusual to
want/need this optimization for a class which is outside of your control.
> EWG4. A class should be able to warrant its own trivial relocatability via
> the attribute `[[trivially_relocatable]]`, as proposed in this paper.
N leaning to A.
One of the reasons we tend to talk about "destructive move" is that
there are lifetime implications. It's not clear that this can be
correctly expressed via an attribute. It seems like users would need to
call a special flavor of dtor.
(I'm also far from convinced this is an "acceptable" use of an attribute.)
> EWG6. A class should be able to warrant its own trivial relocatability as
> proposed in this paper, but we prefer to see a contextual keyword rather
> than an attribute.
Strongly N.
Again, this is too leading. The correct solution might be:
class Foo
{
Foo(Foo~ other) = default; // relocating ctor
...
};
...which isn't really "a contextual keyword".
> EWG7. If a trait with the semantics of `is_trivially_relocatable<T>` is
> added to the `<type_traits>` header, the programmer should be permitted to
> specialize it for program-defined types (i.e., we want to see that trait
> itself become a customization point analogous to `std::hash`).
Weakly F.
This seems redundant with EWG3.
> EWG8. Trivial relocatability should be assumed by default. Classes such as
> those in Appendix C
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1144r0.html#non-trivial-samples>
> should indicate their non-trivial relocatability via an opt-in mechanism.
If you *literally* meant "all" classes, vs. e.g. those that meet some
reasonable criteria, then SA leaning toward OMDB.
> EWG9. To simplify conditionally trivial relocation
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1144r0.html#sample-conditional>,
> if an attribute with the semantics of `[[trivially_relocatable]]` is added,
> it should take a boolean argument.
I'm not even going to answer this one. As others, *way* too leading as
far as assuming a particular approach which does *not* have consensus.
> LEWG13. The type trait `is_trivially_relocatable<T>` should be added to the
> `<type_traits>` header, under that exact name, as proposed in this paper.
F.
In practice, I'm not sure how useful the other two will be.
> LEWG14. We approve of a trait with the semantics of
> `is_trivially_relocatable<T>`, but possibly under a different name. (For
> example, `is_bitwise_relocatable`.)
F, I guess.
Seems a bit redundant with LEWG13, but I guess the point is for people
that want to complain about the color of the bikeshed.
EWG1. We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.
EWG2. We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members.
EWG3. Nobody should be able to warrant the trivial relocatability of class `C` except for class `C` itself (i.e., we do not want to see a customization point analogous to `std::hash`).
EWG4. A class should be able to warrant its own trivial relocatability via the attribute `[[trivially_relocatable]]`, as proposed in this paper.
EWG5. A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name.
EWG6. A class should be able to warrant its own trivial relocatability as proposed in this paper, but we prefer to see a contextual keyword rather than an attribute.
EWG7. If a trait with the semantics of `is_trivially_relocatable<T>` is added to the `<type_traits>` header, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to `std::hash`).
EWG8. Trivial relocatability should be assumed by default. Classes such as those in Appendix C should indicate their non-trivial relocatability via an opt-in mechanism.
EWG9. To simplify conditionally trivial relocation, if an attribute with the semantics of `[[trivially_relocatable]]` is added, it should take a boolean argument.
LEWG10. The algorithm `uninitialized_relocate(first, last, d_first)` should be added to the `<memory>` header, as proposed in this paper.
LEWG11. The type trait `is_relocatable<T>` should be added to the `<type_traits>` header, as proposed in this paper.
LEWG12. If `is_relocatable<T>` is added, then we should also add `is_nothrow_relocatable<T>`, as proposed in this paper.
LEWG13. The type trait `is_trivially_relocatable<T>` should be added to the `<type_traits>` header, under that exact name, as proposed in this paper.
LEWG14. We approve of a trait with the semantics of `is_trivially_relocatable<T>`, but possibly under a different name. (For example, `is_bitwise_relocatable`.)
LEWG15. If `is_trivially_relocatable<T>` is added, under that exact name, then the type trait `is_trivially_swappable<T>` should also be added to the `<type_traits>` header.
I'd like to preface my votes with some justification for my views.Firstly, I believe that the concept of trivial relocatability implies the concept of non-trivial relocatability, and not just in the move-construct-and-destruct sense, but via some as yet unspecified mechanism that does not require two objects to exist at the same time - (very) tentatively a memcpy-and-noexcept-repair. This means that we should leave open the path toward such a mechanism.
Secondly, lifetime is *serious* - it accounts for many of the bugs that afflict experienced programmers. In particular I'm worried about behavior classes that own callbacks (or event handlers), since these are typically lambdas capturing `this`, and such classes may well be stored in containers and thus subject to relocation. It should never be easy to make claims about the lifetime behavior of another class. With regards to warranting trivial relocatability of one's own class, this should only be possible if the bases and members are themselves (warranted to be) trivially relocatable; the wrapper class presented above is too prone to abuse to be allowed. There is still an escape hatch to impose trivial relocatability on a third-party class - use `aligned_storage` and construct, move, copy and destruct as appropriate the wrapped class. For the danger involved, this is not an unreasonable amount of work to impose on the programmer.That is, a class should only be able to warrant its own trivial relocatability if it *would* be trivially relocatable but for the presence of its own user-defined special member functions.
This should be similar to and familiar from the concept of explicitly defaulting move constructor, etc. Together, this suggests that the appropriate syntax for warranting trivial relocatability or otherwise should be a special member function that can be defaulted or deleted, but not user-supplied as yet: `RELOCATE = (default|delete);` where:* RELOCATE is a bikeshed placeholder for a special member;* `default` means that the class is trivially relocatable if all its bases and members are trivially relocatable, and otherwise is not (there is no way to "force" trivial relocatability);* `delete` means that the class is not trivially relocatable, even if it would otherwise qualify. (The class can still be relocated by move-construct-and-destruct.)
EWG1. We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.SA, except when their bases and members are themselves relocatable, in which case SF. (The "escape hatch" is to use `aligned_storage`.)
EWG4. A class should be able to warrant its own trivial relocatability via the attribute `[[trivially_relocatable]]`, as proposed in this paper.A (and SA if its bases and members are not trivially relocatable, per EWG1) - I don't think an attribute is appropriate for modifying lifetime behavior.
On Thursday, November 15, 2018 at 4:51:11 PM UTC+1, Matthew Woehlke wrote:On 14/11/2018 18.17, olee...@gmail.com wrote:
> - The suggested semantics seem questionable in the face of a possible
> exception in the middle of the loop. But rather than arguing about the
> specification, I think it should be dropped from the paper. The experts who
> would use this could easily roll their own anyway.
I don't think that's true. As I understand it, this function is, in some
sense, the sole reason the proposal has value. Specifically, it is
specially blessed as being able to actually perform a memcpy but still
DTRT WRT the memory model.
Without it, "the experts who would use this" must continue to rely on
UB, which defeats one of the main objectives of the proposal. (Am I
missing something? If so, please correct me!) [...]
Well, in that case it's not enough. We need the ability to relocate to a destination range that is only partially uninitialized, and backwards too. (Consider vector erase and insert.) So I would continue to rely on UB regardless.
–Arthur
EWG1. We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.
EWG2. We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members.
EWG3. Nobody should be able to warrant the trivial relocatability of class `C` except for class `C` itself (i.e., we do not want to see a customization point analogous to `std::hash`).
EWG4. A class should be able to warrant its own trivial relocatability via the attribute `[[trivially_relocatable]]`, as proposed in this paper.
EWG5. A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name.
EWG6. A class should be able to warrant its own trivial relocatability as proposed in this paper, but we prefer to see a contextual keyword rather than an attribute.
EWG7. If a trait with the semantics of `is_trivially_relocatable<T>` is added to the `<type_traits>` header, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to `std::hash`).
EWG8. Trivial relocatability should be assumed by default. Classes such as those in Appendix C should indicate their non-trivial relocatability via an opt-in mechanism.
EWG9. To simplify conditionally trivial relocation, if an attribute with the semantics of `[[trivially_relocatable]]` is added, it should take a boolean argument.
On Tuesday, 13 November 2018 21:31:40 PST Edward Catmur wrote:
> That is, a class should only be able to warrant its own trivial
> relocatability if it *would* be trivially relocatable but for the presence
> of its own user-defined special member functions.
But this is an interesting concept. If I have two classes A and B, with A a
base class of B, a new version of A may change whether it is trivially
relocatable. What does this mean for B? [...snip...]
The idea is that there are two levels of "opt-in-ness."The first level, [[clang::maybe_trivially_relocatable]], means "I warrant that even though I may have user-provided, non-defaulted, special member functions, I have designed them so that my relocation operation will not do anything substantially different from memberwise relocation." So if all of my member+base subobjects are trivially relocatable (and not mutable and not volatile), then I myself will be trivially relocatable.The second level, [[clang::trivially_relocatable]], means "I warrant that even though I may have user-provided, non-defaulted, special member functions, and even though I may have non-trivially relocatable (or mutable or volatile) subobjects, I have designed them so that my relocation operation will not do anything substantially different from memcpy." So I myself will be trivially relocatable no matter what my subobjects claim about themselves.
If A wasn't trivially relocatable but now is, B could benefit from the
improvement but requires manual intervention to declare so.
If A was trivially
relocatable and B added the attribute, then this is actually worse: now we're
performing trivial relocations where we shouldn't.
Therefore, it needs to be possible for class B to declare that it is
(trivially) relocatable if its base classes are, in spite of it adding one a
user-defined move constructor or destructor. This is achieavable with an
attribute with parameter, as in:
class [[trivially_relocatable(std::is_trivially_relocatable_v<A>)]] B : A
{ ... };
Of course, immediately upon seeing this, we desire a shorthand for depending
on other types' relocatability. Moreover, if this is going to allow for
complex expressions, it's also a good reason to explore either a contextual
keyword or a different mechanism.
> * RELOCATE is a bikeshed placeholder for a special member;
> * `default` means that the class is trivially relocatable if all its bases
> and members are trivially relocatable, and otherwise is not (there is no
> way to "force" trivial relocatability);
That I disagree with, though not strongly so.
struct A { ... };template<bool> struct B_relocate_base : public A { int m; B_relocate_base(B_relocate_base&&); ~B_relocate_base(); };template<> struct [[trivially_relocatable]] B_relocate_base<true> : public A { int m; B_relocate_base(B_relocate_base&&); ~B_relocate_base(); };struct B : public B_relocate_base<std::is_trivially_relocatable_v<A>> {}; // Rule of Zero
Le lundi 12 novembre 2018 02:35:40 UTC+1, Arthur O'Dwyer a écrit :P1144R0 "Object relocation in terms of move plus destroy" was presented to SG17 (EWGI) in San Diego. (Thanks to Corentin Jabot for trying to make it happen!) The paper lists the following straw polls that could have been taken. None of these polls were taken, and no feedback was given on the paper in San Diego.So I'd like to get your opinions! Please reply in this thread with your !votes on any or all of the following statements, in the traditional WG21 straw poll format: "Strongly For" the statement as written; "For" it; "Neutral" (as in, you considered the question and your expert opinion is that you are neutral on it — please do not use this option as a synonym for abstaining due to lack of an opinion); "Against" the statement as written; or "Strongly Against" it.The polls will remain open for one week, until Sunday 2018-11-18. If you don't want your !votes to be public, you can always email them to me privately.I will tally the ballots and report the results in P1144R1, which will appear in the post-San-Diego mailing (submission deadline: 2018-11-26).
> * RELOCATE is a bikeshed placeholder for a special member;
> * `default` means that the class is trivially relocatable if all its bases
> and members are trivially relocatable, and otherwise is not (there is no
> way to "force" trivial relocatability);
That I disagree with, though not strongly so.I now strongly disagree with this, unless somebody can show me how to implement `std::optional<A>` so that it will inherit the trivial relocatability of `A`, without any "forcing." I have tried and failed with libc++'s optional.Part of the philosophical problem is that `optional` implements "destructibility" at a completely different level of the inheritance hierarchy than "move-constructibility." So in order to make all of `optional`'s base classes trivially relocatable, we essentially have to lie to the compiler and pretend that e.g. __optional_destructible_base is "trivially relocatable" when in fact it's not. (In fact, because of the union, it is not even move-constructible! I think that is the practical problem I'm hitting.) I would strongly prefer to have the most derived class, `optional`, take responsibility for all of its behavior as a package deal, without having to saddle every base class with a [[maybe_trivially_relocatable]] attribute which is actually a lie in most cases.So, having investigated this [[maybe_trivially_relocatable]] attribute a little bit, I am currently of the opinion that we still need [[trivially_relocatable]] (with or without a boolean parameter, but in a form that is not dependent on the kindness of subobjects). At the same time, [[maybe_trivially_relocatable]] looks like it will make some classes, such as `vector`, a bit easier to write — if also a bit more subtle in cases like that _LIBCPP_DEBUG situation.–Arthur
P1144R0 "Object relocation in terms of move plus destroy" was presented to SG17 (EWGI) in San Diego. (Thanks to Corentin Jabot for trying to make it happen!) The paper lists the following straw polls that could have been taken. None of these polls were taken, and no feedback was given on the paper in San Diego.So I'd like to get your opinions! Please reply in this thread with your !votes on any or all of the following statements, in the traditional WG21 straw poll format: "Strongly For" the statement as written; "For" it; "Neutral" (as in, you considered the question and your expert opinion is that you are neutral on it — please do not use this option as a synonym for abstaining due to lack of an opinion); "Against" the statement as written; or "Strongly Against" it.The polls will remain open for one week, until Sunday 2018-11-18. If you don't want your !votes to be public, you can always email them to me privately.I will tally the ballots and report the results in P1144R1, which will appear in the post-San-Diego mailing (submission deadline: 2018-11-26).
Here are the polls. Please vote in any or all of them, but only after reading the paper. When a poll says "...as proposed in this paper," it's referring to the formal wording from P1144R0. You would have to read that formal wording to know what's being asked!---------------------------------------
EWG1. We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism.
EWG2. We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members.
EWG3. Nobody should be able to warrant the trivial relocatability of class `C` except for class `C` itself (i.e., we do not want to see a customization point analogous to `std::hash`).
EWG4. A class should be able to warrant its own trivial relocatability via the attribute `[[trivially_relocatable]]`, as proposed in this paper.
EWG5. A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name.
EWG6. A class should be able to warrant its own trivial relocatability as proposed in this paper, but we prefer to see a contextual keyword rather than an attribute.
EWG7. If a trait with the semantics of `is_trivially_relocatable<T>` is added to the `<type_traits>` header, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to `std::hash`).
EWG8. Trivial relocatability should be assumed by default. Classes such as those in Appendix C should indicate their non-trivial relocatability via an opt-in mechanism.EWG9. To simplify conditionally trivial relocation, if an attribute with the semantics of `[[trivially_relocatable]]` is added, it should take a boolean argument.
LEWG10. The algorithm `uninitialized_relocate(first, last, d_first)` should be added to the `<memory>` header, as proposed in this paper.
LEWG11. The type trait `is_relocatable<T>` should be added to the `<type_traits>` header, as proposed in this paper.
LEWG12. If `is_relocatable<T>` is added, then we should also add `is_nothrow_relocatable<T>`, as proposed in this paper.
LEWG13. The type trait `is_trivially_relocatable<T>` should be added to the `<type_traits>` header, under that exact name, as proposed in this paper.
LEWG14. We approve of a trait with the semantics of `is_trivially_relocatable<T>`, but possibly under a different name. (For example, `is_bitwise_relocatable`.)
LEWG15. If `is_trivially_relocatable<T>` is added, under that exact name, then the type trait `is_trivially_swappable<T>` should also be added to the `<type_traits>` header.
-----------------------Discussion and comments on P1144R0 is also welcome — preferably in the original discussion thread, or via private email, but if it winds up in this thread, I'm okay with that.Thanks,Arthur