[optional] memory use for optional refs and ptrs

Hello, I'm looking into boost::optional<> as a replacement for some of my code which has to deal with optional values. However, it seems that cases which are usually space-efficient optionals (e.g., ptrs in the form of a null-ptr) do not have template specializations. In other words, boost optional templates store a bool and the memory footprint of its template parameter, regardless of type. I.e., optional references and pointers take their space plus the space of an extra bool. Is there a reason for this? Thanks, Rutger

2010/10/5 John Reid <j.reid@mail.cryst.bbk.ac.uk>
I understand, that a null pointer means the same as lack of a pointer. Therefore boost::optional<> colud be specialized for pointers to take advantage of that, and not store a bool besides the pointer in order to save space. I would also like to know, if and why this space optimization is/is not implemented. Regards Kris

On 05.10.2010 15:54, Krzysztof Czainski wrote:
In your use case. The idea has been discussed on the list before, and IIRC, the conclusion was that the library simply cannot rely on the user not wanting to have a null pointer in an optional. I could see a trait for optional specifying if a type has a natural empty value, and if so, which. Sebastian

On 5 Oct 2010, at 15:11, Sebastian Redl wrote:
Yes, for example while NULL is a sensible pointer to store, I decided I would never want to represent (void*)1, so I specialised boost::optional to use that. It is also possible to come up with impossible states for most standard library objects (std::vector, std::list) if you know how they are stored internally. However I'm not sure such code could be submitted to boost.

On 2010-10-05 16:37, Christopher Jefferson wrote:
Yes, for example while NULL is a sensible pointer to store, I decided I would never want to represent (void*)1, so I specialised boost::optional to use that. It is also possible to come up with impossible states for most standard library objects (std::vector, std::list) if you know how they are stored internally. However I'm not sure such code could be submitted to boost.
This is the stuff I am expecting in the first place: A nice and clean interface, and implemented in an efficient way. Cheers, Rutger

On 05/10/2010 11:11 a.m., Sebastian Redl wrote:
Exactly. optional<> cannot decide *by itslef* that a particular value happens to be equivalent to an uninitialized state. That is, a null pointer is not neccesarily the same as none. This is particulary true in a generic design when the type wrapped is unconstrained (i.e. T can be anything, including a pointer) and the condition of uninitialized state *must* be strict (i.e. not *any* value being given)
I could see a trait for optional specifying if a type has a natural empty value, and if so, which.
This and other desirable policies has also been discussed, but the general idea of a policy-based design was rejected for this utility. There where lengthly discussions about such designs for "simple wrappers" like shared_ptr<> or optional<> several years ago. The simple rational being that it clutters the compile-time interface. -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

On 05/10/2010 01:09 p.m., Jeffrey Lee Hellrung, Jr. wrote:
What about it? -- --- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

On 5 October 2010 12:55, Fernando Cacciola <fernando.cacciola@gmail.com>wrote:
It's convenient to pass optional values as pointers, even though one would much prefer passing them as optional references. void foo(Data* output) // no way to tell if implementation supports the output to be null void foo(optional<Data&> output) // clearly the intention is that the output is optional, and that the implementation is responsible for checking if output is assigned by caller or not optional<T&> could unless I'm mistaken remove the member boolean, since there is no such thing as a null reference. / Christian

On 05/10/2010 03:27 p.m., Christian Holmquist wrote:
Ok, yes, in that case there is no possible doubt about the semantics, so the boolean can be spared. OTOH, is such a corner case that I don't imagine myself doing it in the sort term. -- --- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

On 2010-10-06 00:19, Fernando Cacciola wrote:
Although it isn't the most important case for me, it has its own section in the documentation, and I will probably be using lots of these. What also doesn't seem right to me is that, e.g., struct A { int a; double b; double c; std::string d; }; struct B { boost::optional< int > a; boost::optional< double > b; boost::optional< double > c; boost::optional< std::string > d; }; the size of A is 32 bytes in this case, and the sizeof B is 56 bytes: almost doubled. So, while it may be argued that the case above is a corner case, too, I don't it's an acceptable penalty to anyone to pay 24 bytes for something that can be stored in 4 bits and/or in the type itself. What would make optional useful to me, is a kind of optional that allows the boolean set/get stuff to be done (and possibly stored) outside of the optional itself. E.g., by means free functions that can be overloaded (and throw in the ability of defining tags to the optional template-parameters to be able to define a bit# in a bitset). Cheers, Rutger

Rutger ter Borg
I can imagine it happening sooner with patches to the code and documentation.
I imagine it isn't so rare for those in the habit of using optionals, but then again, I find a raw pointer to have just the needed semantics that I wouldn't use optional for that case. (I don't find myself wanting to have an optional pointer that might be null when present.)
That's an interesting scenario, but is it likely that so many pieces would be optional in a single context like that? (I haven't looked, but I do hope that the bool follows the optional value to reduce padding overhead.)
I wouldn't want that to replace the current design, but it would be useful as an alternative to the current design or an extension of it. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 2010-10-06 13:11, Stewart, Robert wrote:
This is likely indeed, if you're going to model message structures, the most direct representation commonly contains a great deal of optionals.
(I haven't looked, but I do hope that the bool follows the optional value to reduce padding overhead.)
It doesn't, the boolean is followed by the optional value (see boost/optional/optional.hpp lines 447-448).
I wouldn't want that to replace the current design, but it would be useful as an alternative to the current design or an extension of it.
I agree. Cheers, Rutger

On 06.10.2010 14:09, Rutger ter Borg wrote:
I really don't think it makes a difference. Unless you're using compiler-specific packing instructions, the size of a struct will always be a multiple of the largest alignment of any of its subobjects. In other words, no matter where you place the bool, it will take as much space as the alignment of the value. Sebastian

Sebastian Redl wrote:
When the bool follows the value, it can occupy otherwise unused padding between data members. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 06.10.2010 14:26, Stewart, Robert wrote:
I really don't think so. Maybe in theory, but not in practice, for various reasons. One is that an ABI that allows this would be very complicated to specify. Another is that optional uses something like aligned_storage, which hides padding of the type is is a placeholder for. And even the theory is only a maybe - depending on exact wording of the address ordering rules of C++, it might simply be forbidden, or the only allowed thing might be to place things in trailing padding of the directly preceding element. But as I said, aligned_storage ruins all optimization opportunities anyway. A more interesting question is whether placing the bool at the end would mean that since the bool's padding is now trailing, other stuff can be placed in there. I've read and re-read the Common C++ ABI, which is an evil, hard-to-read (and sometimes downright misworded) document, and I have come to the conclusion that compilers that follow it can't do that. Maybe compilers that follow other ABIs. Sebastian

On 10/06/10 08:28, Sebastian Redl wrote:
http://article.gmane.org/gmane.comp.lib.boost.devel/209212 followed by: struct C { int a; bool ta; double b; bool tb; double c; bool tc; std::string d; bool td; }; int main(void) { std::cout<<"sizeof(A)="<<sizeof(A)<<"\n"; std::cout<<"sizeof(B)="<<sizeof(B)<<"\n"; std::cout<<"sizeof(C)="<<sizeof(C)<<"\n"; return 0; } showed sizeof(B) = sizeof(C), justifying Sebastian's doubt. -Larry

On 10/06/10 13:19, Larry Evans wrote:
The reason sizeof(A) == sizeof(bools_A) is that the 4 bools use the padding following the int A::a. IOW, bools_A puts the 4 bools where the int A::a is located, followed by the int. Hence, no extra space is needed. Adding 1 extra bool at the start causes the sizeof(bools_A) to jump by 8. This is shown by output of the attached: alignment_of<A>::value=8 sizeof(A)=32 sizeof(B)=56 sizeof(Atags)=56 sizeof(tagsA)=56 sizeof(A_bools)=40 sizeof(bools_A)=32 sizeof(bools)=4 sizeof(int)=4 alignment_of<bools>::value=1

Larry Evans wrote:
If any of the types, other than bool, were smaller than int, I think you'll find some differences, but the answer does depend upon compiler options. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 06.10.2010, at 20:22, Stewart, Robert wrote:
If any of the types, other than bool, were smaller than int, I think you'll find some differences, but the answer does depend upon compiler options.
No, and no. First, this snippet: struct I { double d; char c; // expect 7 bytes padding }; static_assert(sizeof(I) == 16, "Bad size for I"); struct O { I i; short s; // placed in padding? }; If your theory is true, then the compiler would place s in the padding of i in the layout of O. Trying this out with Clang (which is ABI-compatible with GCC, so GCC would give the same result) shows that the size of O is 24, meaning that s is not placed in the padding. I can't try MSVC. Maybe it does things differently. Anyway, I can further state with conviction that no compiler for non-embedded platforms changes its ABI based on compiler options, except perhaps a compiler option intended to do specifically that. (Clang has an option to switch between various ABIs.) But no debug or optimization option will change the object layout algorithm. To do so would be pure insanity, because it would mean that you cannot link debug versions of code with non-debug versions, optimized versions with unoptimized ones. Well, MSVC might do it. But even there I very much doubt it. Sebastian

[Sebastian Redl]
Here's an extremely useful undocumented option: C:\Temp>type meow.cpp struct Foo { double d; char c; // expect 7 bytes padding }; static_assert(sizeof(Foo) == 16, "Bad size for Foo"); struct Bar { Foo i; short s; // placed in padding? }; C:\Temp>cl /EHsc /nologo /W4 /c /d1reportSingleClassLayoutFoo meow.cpp meow.cpp class Foo size(16): +--- 0 | d 8 | c | <alignment member> (size=7) +--- C:\Temp>cl /EHsc /nologo /W4 /c /d1reportSingleClassLayoutBar meow.cpp meow.cpp class Bar size(24): +--- 0 | Foo i 16 | s | <alignment member> (size=6) +--- MSVC does have options that affect layout (most notoriously, /Zp changes packing, and then there are the obscure options like /vd2 and /vmg), but optimizations don't. Debug versus release mode (/MTd versus /MT, or /MDd versus /MD) affects which Standard Library implementation you link to. By default, the IDE compiles in debug mode without optimizations, and in release mode with optimizations, but they are not inherently tied together. Mixing debug and release mode will usually trigger linker errors, and it's an extremely bad idea, because the representations of Standard Library objects like vector are sensitive to debug versus release - but the library is choosing to add or remove data members, the compiler's layout algorithm is not changing. Stephan T. Lavavej Visual C++ Libraries Developer

Sebastian Redl wrote:
That's not what I was suggesting. short can have alignment requirements, but bool and char do not. I was suggesting that this: struct P { short s; char c; short t; char d; }; could occupy less space than if the chars and shorts were reversed. That is, that P::c could occupy padding between P::s and P::t and P::d could occupy padding between a P instance and something following it in another composite. Doing so would not violate an ABI, unless the ABI specifically disallowed it, because it can be established as the expected layout in those cases. Applying this to the optional case: struct Q { optional<short> s; optional<short> t; }; If the bools in the optionals were to follow the shorts, then Q's size could be smaller than if they precede the shorts. The use of aligned storage doesn't even matter in that case as it would dictate the alignment of the shorts. I checked the above using 32 and 64 bit GCC 4.1.2 and ICC 11.0.083 (which maintains GCC ABI compatibility), and 32 bit MSVC 9 and found that the size did not differ, so for those compilers, at least, my assertions are incorrect. That doesn't disprove the theory, but does disprove its application in those cases. Compilers can be instructed to pack structures differently, in which case they might be coerced to satisfy my theory, even if they wouldn't by default. However, that doesn't affect optional, which was the point of this discussion. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 07.10.2010 13:22, Stewart, Robert wrote:
True, but that requires a type where alignof(T) > sizeof(T), which only happens if you override alignment requirements with attributes or something similar. Which aligned_storage actually wouldn't understand. (Such types are dangerous anyway. VC++, at least, doesn't actually guarantee proper alignment for every instance of such a type, in particular not for members of an array of such type.) But you're missing my point. The whole exercise is useless. For layout purposes, boost::optional is a struct containing two members. It can be written either as { T t; bool b; } or { bool b; T t; }. Assuming alignof(bool) == sizeof(bool) == 1 (which is actually not the case in some old ABIs), it holds true in both cases that alignof(optional) == alignof(T) and sizeof(optional) == 2 * sizeof(T). Because layout algorithms treat member types as opaque, it doesn't matter where the padding in optional is - no compiler will embed members of a containing struct in the padding of the optional. Let me give you an example. Here's a struct that actually shrinks if you reorder the members: struct A { char c1; int i; char c2; }; // sizeof == 12 struct A_Opt { int i; char c1; char c2; }; // sizeof == 8 But this only works because all members are top-level. Contained structs are opaque! This means that if I change A_Opt to pack the first two members together, the size optimization is lost! struct A_Bad { struct { int i; char c1; } bad; char c2; }; // sizeof == 12 This is exactly the problem you face when trying to optimize optional. It doesn't matter that you move the padding to the end of the struct. The compiler still won't use it. Examples validated with Visual Studio 2010. Sebastian

Sebastian Redl wrote:
OK, I see that.
Got it.
Right. That's what I was thinking of, but went too far in applying it to the case of there being just one small field.
That much I didn't expect, but I was thinking that the size of optional could be sizeof(T) + sizeof(bool) rather than 2 * sizeof(T), which I thought could have been useful in some cases. I understand the reasons why that would not be so now. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 10/07/10 06:22, Stewart, Robert wrote: [snip]
The code: https://svn.boost.org/trac/boost/browser/sandbox /variadic_templates/libs/composite_storage /sandbox/layout_all.1.cpp produces output shown in the attachment. tagPs is with char's first, Ptags is iwht char's 2nd. Both sizes are same: sizeof(tagPs)=8 sizeof(Ptags)=8 the other output shows the alignments and offsets of each component was well as the padding. The offsets are listed starting from last to first element in the structs. the output prefixed with layout0 shows the layout for an empty struct. HTH. -Larry

Rutger ter Borg wrote:
Just replicate the tuple interface but accpet and return optional<T> for each element and store it as a bit_vector and a regular tuple internally. Call it tuple_optional or tuptional or some such. Such a library could be implemented, documented, tested and ready for review in about one week flat, but I have no interest in either writing it or using it. I don't use optional either. Regards, Luke

On 2010-10-06 19:19, Simonson, Lucanus J wrote:
Just replicate the tuple interface but accpet and return optional<T> for each element and store it as a bit_vector and a regular tuple internally. Call it tuple_optional or tuptional or some such. Such a library could be implemented, documented, tested and ready for review in about one week flat, but I have no interest in either writing it or using it. I don't use optional either.
Sounds like a good starting point (or fusion vectors). Is there some kind of facility that is able to point to "padding space" in aligned structures? (perhaps a facility of the alignment stuff in boost)? Cheers, Rutger

On 10/06/10 13:33, Rutger ter Borg wrote: [snip]
[snip] There's: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/boost/co... It's used to calculate the distance between the end of 1 element in a tuple and the start of the next element so that that next element will have the proper alignment. IOW, if: aligned_offset<Offset,Alignment>::remainder != 0 then there will be padding in the amount: value-Offset That is, IIRC. HTH. -Larry

On 10/06/10 13:59, Larry Evans wrote:
[snip] A more complete facility use is here: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/libs/com... which produces output: mpl::size<result_t>=3 ( size=1, align=1) ( size=4, align=4) ( size=8, align=8) composition < offset=8 , size=16 , align=8
padding_one=0 padding_all=0 composition < offset=4 , size=8 , align=4
padding_one=3 padding_all=3 composition < offset=0 , size=1 , align=1
padding_one=0 padding_all=3 layout0 < size=0 , align=1
which shows the padding after the char is 3 in order to make the alignment of the int at 4. HTH. -Larry

On 10/07/10 07:31, Rutger ter Borg wrote:
You're welcome. The reusable part of the code has been refactored into: http://svn.boost.org/svn/boost/sandbox/variadic_templates /boost/composite_storage/utility /show_layout_all_of_aligned.hpp so that it on different struct's rather than just the struct's in the current example driver. The output produced on the example struct's in: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates /libs/composite_storage/sandbox/layout_all.1.cpp is now in tabular format: A_type =========== ***components*** ---------------- num size align sum_size 1 4 4 4 2 8 8 12 3 8 8 20 4 8 8 28 ***composite*** --------------- num size align pad sum_pad offset 5 32 8 0 0 _ 4 32 8 0 0 24 3 24 8 0 0 16 2 16 8 4 4 8 1 4 4 0 4 0 0 0 1 _ _ _ A_bools_type =========== ***components*** ---------------- num size align sum_size 1 4 4 4 2 8 8 12 3 8 8 20 4 8 8 28 5 1 1 29 6 1 1 30 7 1 1 31 8 1 1 32 ***composite*** --------------- num size align pad sum_pad offset 9 40 8 4 4 _ 8 36 8 0 4 35 7 35 8 0 4 34 6 34 8 0 4 33 5 33 8 0 4 32 4 32 8 0 4 24 3 24 8 0 4 16 2 16 8 4 8 8 1 4 4 0 8 0 0 0 1 _ _ _ bools_A_type =========== ***components*** ---------------- num size align sum_size 1 1 1 1 2 1 1 2 3 1 1 3 4 1 1 4 5 4 4 8 6 8 8 16 7 8 8 24 8 8 8 32 ***composite*** --------------- num size align pad sum_pad offset 9 32 8 0 0 _ 8 32 8 0 0 24 7 24 8 0 0 16 6 16 8 0 0 8 5 8 4 0 0 4 4 4 1 0 0 3 3 3 1 0 0 2 2 2 1 0 0 1 1 1 1 0 0 0 0 0 1 _ _ _ which shows the padding between individual fields and the sum of the padding. This shows why putting the bools first (bools_A_type) saves space. As mentioned before the 4 bools are placed in the padding present in the padding required by A_type; hence, sizeof(A_type) == sizeof(bools_A_type). Hope the tabular output makes it easier to see the reason for space usage. -Larry

On 6 October 2010 02:56, Rutger ter Borg <rutger@terborg.net> wrote:
Although [references aren't] the most important case for me, it has its own section in the documentation, and I will probably be using lots of these.
Why? What is the advantage over using a raw pointer?
What bit pattern can be used for an int which says it hasn't been set? Optional models "the variable is not set." You want something different. Why not just create a different class to model what you want? -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

On 2010-10-06 20:21, Nevin Liber wrote:
None at this time. It's just that an optional<T&> exactly does what everyone usually does with null-pointers and stuff. I thought it might be clearer and less prone to error.
In this particular example I'm showing the space efficiency of different classes (see http://article.gmane.org/gmane.comp.lib.boost.devel/209212), I'm not saying int should have a certain bit pattern for "unset". I'm merely saying that due to the extra boolean and padding, sizeof(B) grows.
I think I know what optional models, and it is clearly what I want. However, I would like to have space-efficient ones. Cheers, Rutger

Hi Rutger,
I think I know what optional models, and it is clearly what I want. However, I would like to have space-efficient ones.
Achieving the space-efficiency via specific values is not an option for the reasons stated before. On the other hand, doing that by some other means is always worth consideration. That has also been discussed in the past, but sadly I don't remember any conclusion. Off the top of my head (and past midnight) I'm thinking that a specialized version of aligned storage that always allocate one extra byte at the end might do the trick. Having said that, there is a problem with your *requirement*. I have had sort of the opposite: replace the bool with a pointer to T, for debugging purposes (out-of-the-box pretty printing). The justification being precisely that the bool takes up the same space anyway. I really liked that change, and I was planing on doing it. Now I'm not so sure, because your's is also valid (if no much more). -- --- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

At Wed, 06 Oct 2010 20:31:30 +0200, Rutger ter Borg wrote:
It seems clear to me that optional<T*> models one more state than you want. You're not interested in "no T*" and "a null T*" as separate states. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 10/06/10 02:56, Rutger ter Borg wrote:
I think the most efficient storage would be in descending order of alignment values followed by the bits for the tags. The reason for this is that a type with a smaller aligned value can be used to fill the padding for the previous type. Since the bool tags have align==1, they could go last. This is shown by the A_sort_bools_type output from: https://svn.boost.org/trac/boost/browser/sandbox/variadic_templates/libs/com... which shows 0 padding using this rule. Of course, as shown by the output for bools_A_type, that's not the only way to get 0 padding for a set of types. The layout_all.1.cpp output is reproduced in the attachment. HTH. -Larry

Rutger ter Borg wrote:
However, it seems that cases which are usually space-efficient optionals
(e.g., ptrs in the form of a null-ptr) do not have template specializations.
In case this applies to your use case: http://cctbx.svn.sourceforge.net/viewvc/cctbx/trunk/tbxx/optional_copy.hpp?revision=11570&view=markup Stores a null pointer if the value is not defined, uses "new" to allocate space for a value if given. This has been very useful for managing objects that are rarely needed: the memory overhead is just one pointer for the common case when the object is not needed. Ralf
participants (15)
-
Christian Holmquist
-
Christopher Jefferson
-
David Abrahams
-
Fernando Cacciola
-
Jeffrey Lee Hellrung, Jr.
-
John Reid
-
Krzysztof Czainski
-
Larry Evans
-
Nevin Liber
-
Ralf W. Grosse-Kunstleve
-
Rutger ter Borg
-
Sebastian Redl
-
Simonson, Lucanus J
-
Stephan T. Lavavej
-
Stewart, Robert