2015-09-25 17:37 GMT+02:00 Andrey Semashev
On 25.09.2015 17:35, Andrzej Krzemienski wrote:
Hi Everyone, I would like to inquire if there would be an interest in Boost in another library for storing optional objects, but working under different design goals.
Compact optional T has (or can have) the same sizeof as T. It uses one indicated value of T to represent the "empty" (or "singular") value. You can declare it like this:
compact_optional
> oi; This reads: we have an optional int, with type int inside, where -1 represents the empty value. It can never have a genuine (non-empty value -1). This can be used, for instance, to wrap the std::string::npos into:
compact_optional
> With the same memory layout as std::string::size_type, but with the special syntax for managing the singular value.
It is not meant to be an alternative to Boost.Optional: it targets a different application space.
The idea looks interesting - I sometimes have to deal with magic values. Currently I prefer to wrap the object into optional<> or at least make the special value not so magic (i.e. so that the code always does the right thing without checking for the magic value).
Hi Andrey, thank you for your reply.
However, I'm not sure I agree with your rationale on the reduced interface and possibly the compact_optional naming.
1. You chose not to provide relational operators for compact_optional because you don't know how to order 'empty' values. I think you don't have to make that decision and simply forward the call to the underlying type. I mean, you always have the stored object constructed in some state and as long as it implements operators you can always use them.
So this is a trade-off between convenience/expressiveness and the potential to detect unintended semantics at compile-time. If there is sufficient argumentation in favor of adding them, I can always do it. As Rob says, this can also be encoded in the policy.
2. compact_optional does not provide direct assignment of the values of the stored type, requiring to manually construct a compact_optional-wrapped value. To me, this is too cumbersome to use while I don't see any wins from this restriction. Besides more typing, this essentially requires to use a typedef to declare and use the compact_optional variable.
Are you proposing a member function like opt.store_raw_value(v); ?
3. Nitpick: the typical name for the getter operation is get(), not value(). I would also have used empty() to test for the magic value but maybe that makes you feel it like a container.
4. Regarding compact_optional naming. While the class can be used for similar purpose as optional, its interface and behavior are significantly different. Perhaps a different name would be better to avoid confusion (e.g. nullable<>).
I am not particularly tied to name compact_optional. I can be persuaded to rename it. On the other hand, I am not in favor of any names containing "null". I am not an English speaker, but no me "null" sounds like "numeric value zero", which makes sense for the pointer, but not for something that just is not. Maybe "singular" or "special".
5. A suggestion: add evp_zero and evp_empty policies. The first uses literal zero as the special value and can be used with numeric (integer and fp) and pointer types. The second uses a default constructed value as the magic value and a member empty() function to test for magic value. This could be useful with containers, strings and ranges.
Agreed on evp_empty, but I fail to see the advantage of evp_zero over the already existing evp_value_init. The later uses the value initialized T, which already is zero for ints, floats and pointers. Or do you expect the comparison to literal 0 to be faster? Regards, &rzej