Among the several changes I've planned to dynamic_bitset there's one which affects semantics and that, therefore, I would like to discuss with you a bit. Note however that the old semantics were never specified in the docs, so this would break nothing but adventurous usages of undocumented features on the users part.
Here's the issue: dynamic_bitset<>::reference currently stores a pointer to its bitset object and an index. For that reason: - after a swap of bitsets, references come to refer to different elements: they get track of the address of the bitset they are referencing, and the bitset has changed its contents. - value changing operations on the dynamic_bitset *don't* invalidate references unless they make the corresponding index out of range (by shrinking the bitset). In other words: semantics are intrinsecally those of a *pair* (bitset address, index); as long as the index remains valid for the pointed to bitset everything is fine. But then one wonders: why not using an index directly? And even if, how could one use a reference considering that all its constructors are private? Both points above are the exact contrary of what one would expect by analogy with references, pointers, or iterators (The standard guarantees that no standard library swap() function invalidates any references, pointers, or iterators referring to *the elements* of the containers being swapped. To state it metaphorically: the elements change containers but references "follow" them). Now, the first question is: ok to change semantics and document the new behavior? (BTW, the new semantics can be implemented much more efficiently, e.g. by storing a pointer to a block and a *precomputed* mask) Second question: any interest in having this new reference<Block> as a separate class? (In this case dynamic_bitset::reference would really become a typedef as stated in the docs, rather than a nested class :-)) Now, for the gurus: this is the current interface of reference: class reference { friend class dynamic_bitset<Block, Allocator>; // the one and only non-copy ctor reference(dynamic_bitset& bs_, size_type bit_); public: operator bool() const; // for x = b[i] bool operator~() const; // flips the bit reference& flip(); // for b[i].flip(); reference& operator=(bool value); // for b[i] = x reference& operator|=(bool value); // for b[i] |= x reference& operator&=(bool value); // for b[i] &= x reference& operator^=(bool value); // for b[i] ^= x reference& operator-=(bool value); // for b[i] -= x reference& operator=(const reference& j); // for b[i] = b[j] reference& operator|=(const reference& j); // for b[i] |= b[j] reference& operator&=(const reference& j); // for b[i] &= b[j] reference& operator^=(const reference& j); // for b[i] ^= b[j] reference& operator-=(const reference& j); // for b[i] -= b[j] }; Note the last two groups of 5 functions: they are identical except that those of the first group take a bool and those of the second one a const reference &. But since we have an operator bool() const wouldn't the first group be enough? In effect, declaring the copy-assignment operator has the pleasant effect to force an explicit definition, showing that the shallow-copy is intentional, but what about the other 4 functions? What's their purpose? If we drop them, an expression like b[i] |= b[j] changes from (b.operator[](i)).operator |= ( b.operator[](j) ) to (b.operator[](i)).operator |= ( b.operator[](j).operator bool() ) But I can't see any problem with that, even with self-assignment. Am I missing something? Genny. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost