News for hackers. Stuff that matters.
Re:C++11 Tuple Implementation Details (2012) by Kranar on Friday February 05, 2021 @09:38PM (#26043621)
>I really hate the C++11 tuple implementation as I have never figured out a way to construct it from a recursive template algorithm.

Use a combination of std::forward_as_tuple [1] and std::tuple_cat [2] to successively construct each element one-by-one and in place.

If you have a specific use case I could show you how to use them.

[1] https://en.cppreference.com/w/cpp/utility/tuple/forward_as_t...

[2] https://en.cppreference.com/w/cpp/utility/tuple/tuple_cat

Re:C++11 Tuple Implementation Details (2012) by comex on Saturday February 06, 2021 @12:02AM (#26044259)
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?

Re:C++11 Tuple Implementation Details (2012) by Kranar on Saturday February 06, 2021 @12:41AM (#26044413)
You 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.
Re:C++11 Tuple Implementation Details (2012) by comex on Saturday February 06, 2021 @01:58AM (#26044712)
So 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.

Re:C++11 Tuple Implementation Details (2012) by Kranar on Saturday February 06, 2021 @02:09AM (#26044755)
Yep, 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.

Re:C++11 Tuple Implementation Details (2012) by Lvl999Noob on Saturday February 06, 2021 @12:26AM (#26044354)
In 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.
Re:C++11 Tuple Implementation Details (2012) by saurik on Monday February 08, 2021 @04:21PM (#26070322)
Correct. 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.