4 ms·
Not saurik, but that would involve a whole lot of redundant move constructions (to go from each tuple to the next one) which may or may not be optimized away.
by comex 6y ago
Not saurik, but that would involve a whole lot of redundant move constructions (to go from each tuple to the next one) which may or may not be optimized away.
But I think the same problem would apply to any class: you can't construct an object without constructing its fields. The workaround would be to wrap each field in a union so that it can be trivially default constructed, then use placement new. But then where would you track how many fields have been initialized so far? In a separate iterator object? What would the tuple's destructor do?
- Lvl999Noob 6y agoIn that case, isn't this the use case for the Builder Pattern? Use a separate type that knows how to work with partially initialized tuples and correctly destructs them.
- saurik 6y agoCorrect. The implementation I had in mind when I said "internal iterator"--and which I think I've coded before back almost two decades ago--is that the tuple one-by-one in-order does a placement new on each of its elements, calling a templated callback you provide which returns the element (so you get RVO through to the placement new); in the case of an exception, it knows which it has already done by code (not by state) and so can deconstruct the appropriate objects.
- Kranar 6y agoYou use the std::forward_as_tuple to eliminate all moves. The std::forward_as_tuple is used to collect arguments to each constructor so that at the end you can build the final tuple in place.
- comex 6y agoSo you're saying that you'd build a tuple (or some other structure) of tuples of references to construction arguments. You'd still be constructing a series of successively larger objects from smaller ones, but those objects are made up of a bunch of references, and references are trivially copyable from the implementation's perspective (though not from the standard's). So those constructions would likely be optimized away via memcpy elimination, or, even if they weren't, they'd be relatively cheap. Am I understanding correctly? I suppose that works, as long as you can determine all the construction arguments in advance. It wouldn't work if, e.g., later elements of the tuple are constructed with pointers into earlier elements, so that you'd need the earlier elements to already be constructed before computing the construction arguments for the later elements.
- Kranar 6y agoYep, that's the idea. It's done in several parts of the standard library to in-place construct objects, usually via std::piecewise_construct. >It wouldn't work if, e.g., later elements of the tuple are constructed with pointers into earlier elements... That's right but there's no way to construct a tuple in this manner. You can construct a tuple with some default values and then after construction have elements of the tuple point to others, but you couldn't possibly construct a tuple where elements of the tuple are pointing to one another.