
why is boost::optional laid out so that the bool comes before the object's placeholder/storage? this takes up to 7 extra bytes of storage with default alignement and, more importantly, it forces pointer offset adjustment/calculation when accessing a boost::optional<> through a pointer (and trying to access the actual contained object)... it also makes life harder for those of us keen to hackery ;) because it makes the address of an optional different from the address of the actual object within the optional... ps. it would be 'cool' if all of the functionality from boost::optional<> not related to the 'is initialized' bool (conditional destruction, etc...) could be extracted into a separate class (usefull for cases where you have to delay/in-place construct an object but are certain that you will construct it by the point where it needs to be used or destroyed...so you do not need the 'conditional' overhead)... -- "That men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley

AMDG Domagoj Saric wrote:
These two structs should both take up 16 bytes. You don't save anything by reordering the members. struct s1 { bool initialized; double value; }; struct s2 { double value; bool initialized; };
Is the difference in performance actually measurable in any way?
Um, you shouldn't rely on this anyway. The standard only makes guarantees about the addresses of sub-objects for POD types.
In Christ, Steven Watanabe

"Steven Watanabe" <watanabesj@gmail.com> wrote in message news:4AC4EDDE.5070606@providere-consulting.com...
true :blush: should've checked the issue beforehand ;) but it was more of a side note/'thought' anyway...my main concern was with following issue...
well, "actually measurable difference in performance" is, imho, kind of a "grey area"/"subjective metric"...and a library should not, imnho, make 'real world' usage assumptions if it does not have to...and in this case, as far as i can see/imho, it does not have to...that is, from the standpoint of boost::optional<> it makes no difference what layout it uses, but one of those layouts does cause the usage of more complicated addresing modes/extra adjustment code (depending on the platform) in certain cases...the fact that this is infinitesimally insignificant compared to a single default construction of a std::sstream ;-D makes no difference (if i am not mistaken with the assumption that the actual layout makes no difference from the boost::optional<> point of view)... -- "That men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley

"Steven Watanabe" <watanabesj@gmail.com> wrote in message news:4AC4EDDE.5070606@providere-consulting.com...
and, if i'm not mistaken, for class sub-objects that belong to the same "access section"...although, yes, the point is still moot from a standard-pure POV as boost::optional<> is free to use base classes for implementation and it in fact does... -- "That men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley

"Mathias Gaunard" <mathias.gaunard@ens-lyon.org> wrote in message news:ha5309$6jc$1@ger.gmane.org... Domagoj Saric a écrit :
that's true for 'most' code but not all...otherwise placement new would be equally 'pointless'/indication of bad design/code organization... ...because that is what i was whishing for to be extracted from optional<> - the placement new/in-place construction + aligned storage + reference workarounds&co. wrapped up machinery... ...for example: 1. template <class Data, class Widget> class DataWithUI : public Data { void createUI(); void destroyUI(); boost::optional<Widget> ui; } where ui is always created after data and always destroyed before data...and there are many such pairs...if all uis are created and destroyed at the same time (for example with/by their parent) there is no need to track their lifetime individually hence no need for the individual bools for each "optional" ui... 2. you have fusion containers of non default constructible objects and/or objects that you cannot construct all at once (a trivial example: one of the parameters to the constructor of the objects is the order/index of the object in the fusion container) but need to, for example, construct them in a loop...so you wrap that fusion container and ensure proper construction/initialization and complete destruction in the constructor/destructor of the wrapper - this then gives you single deterministic points of construction and destruction (for all the contained objects) making the individual bools redundant... 3. the simple bool/true-false lifetime management is not enough for a situation, e.g. you have a reference counted singleton...then the following source code: ... boost::optional<Singleton> singleton; ... if ( !ref_count++ ) singleton = boost::in_place(); will actually produce the following binary code if ( !ref_count++ ) { if ( singleton.is_initialized() ) ~singleton(); singleton = boost::in_place(); } with similar redundancy in the destructor... -- "That men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley

On Tue, Oct 27, 2009 at 7:13 PM, Domagoj Saric <dsaritz@gmail.com> wrote:
4. An in-place fast pimpl. see Herb Sutter's http://www.gotw.ca/gotw/028.htm for why not to do this. Yet I've done it anyhow. I templatized it and it probably turns out to be the same as most of the internals of optional<>. I also managed to mitigate most of the list of his concerns for why not to do this. Still not something to do without good reason, but manageable. eg: // just forward declare CRITICAL_SECTION, // instead of including <windows.h> // and polluting everything with its macros: struct CRITICAL_SECTION; class CriticalSection // windows version of cross-platform CS { in_place_pimpl<CRITICAL_SECTION, 16> pCS; // 16 is sizeof(CRITICAL_SECTION) //... }; In the cpp file for CriticalSection, we check that sizeof(pCS) really is 16, properly aligned, etc. The in_place_pimpl<> also forwards constructor args, implements operator=, etc. But it is not just for in_place_pimpl, it is for any time you need finer control over construction/destruction/storage. In fact, each of those is a policy to the underlying reinterpret_bytes<> or whatever I called it. I probably should have looked at the internals of optional<>, would have made my life easier... Tony

Am Wednesday 28 October 2009 15:31:55 schrieb Gottlob Frege:
that is not the same thing as gottlob was proposing. boost::optional<> doesn't have the problems herb sutter lists, and a type that is only used for in place construction, without optional's conditional bool, wouldn't either. I've been missing such a type, too, but I think it should be part of the boost in place utility instead of boost::optional: http://www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html see "container-side usage" there.

that is not the same thing as gottlob was proposing.
What Domagoj was asking for was: ...because that is what i was whishing for to be extracted from optional<> - the placement new/in-place construction + aligned storage + reference workarounds&co. wrapped up machinery... with examples of uses. I gave another example of where those internals could be useful, and what I ended up doing.
agreed. I was off on a tangent about just my example.
Yes, in-place is again similar. At least it handles the construction issues. I see it as either my templates have 10 overloads, or I use in_place (easier for me) and make my users use it as well (bit harder for them). For a fast_impl, the user is probably another library writer, already doing forwarding, so I don't see that as a problem. Definitely lots of code doing similar things - more reasons why it could maybe be split up / reorganized / grouped / etc. Of course, C++0x vararg templates + 'perfect forwarding' would make things easier and change much of this. Tony

Domagoj Saric wrote:
Make createUI the constructor and destroyUI the destructor.
That's a good point. You initialize things in groups so you don't need a boolean per thing. The solution is easy: instead of a structure of optional things, make an optional structure of things; you transform N booleans into one, as expected.
You know what position a tuple element is going to be in before initializing the tuple, surely.
Well, first, I don't think this is so easy. Are you taking into account that constructing the subsequent elements might throw, and that you therefore need to destruct the previous ones? Otherwise, I don't understand that point, since tuples and loops aren't exactly things that go well together. Maybe you meant something else than tuples when you were talking of fusion containers?
shared_ptr already provides delayed construction, I don't see why you would want to use optional here? Because you want to store the memory in static memory maybe? For that, just use boost::aligned_storage and placement new, works with shared_ptr like the rest just fine.

"Mathias Gaunard" <mathias.gaunard@ens-lyon.org> wrote in message news:hca1im$v6k$1@ger.gmane.org...
sorry..i'll respond only to this last point (for the sake of a clearer discussion) because it actually contains the main issue (my code 'wish')... ...yes :) aligned_storage and placement new (plus the few additional workarounds for 'quirky' cases) are exactly/all i want...but because it is a relatively often used idiom i would like not to have to write it all manually every time...but rather have small class that wraps it up and allows me to call construct() and destruct() (with boost::in_place support and even the 'bool' left in debug builds for asserting correct usage)... -- "That men do not learn very much from the lessons of history is the most important of all the lessons of history." Aldous Huxley
participants (6)
-
Domagoj Saric
-
Domagoj Saric
-
Gottlob Frege
-
Mathias Gaunard
-
Stefan Strasser
-
Steven Watanabe