5

I just watched cppcon talk about Bloomberg datum, variant type that uses redundancy in IEEE754 format to encode what type is stored in datum.

So I was wondering does C++ standard allow for implementations to implement std::optional more efficiently by using the same trick.

Note that this would require that sometimes binary representation of a double stored in optional does not match the binary representation of double passed to constructor.

notes: I care about standard allowing this or not, I know most/all implementations will not bother.

I know IEEE754 is not mandated by the standard, but it is allowed and checkable by implementation.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 2
    How would that not be allowed, short of an explicit prohibition by the standard? Note that UB does not apply to the implementation the same way it applies to user code. – Baum mit Augen Oct 22 '18 at 11:20
  • 1
    *"I know most/all implementations will not bother"* - Why the negativity? – StoryTeller - Unslander Monica Oct 22 '18 at 11:22
  • 2
    @StoryTeller STL is a huge library, and std::optional is extremely rarely used... and most STL implementations have only a few fulltime devs working on it. – NoSenseEtAl Oct 22 '18 at 11:48
  • @BaummitAugen like I said it breaks the binary represantation of an value. Also there could be other issues I did not think of, that is why I asked. – NoSenseEtAl Oct 22 '18 at 11:49
  • 3
    I haven't seen that talk, but under IEEE-754, **every** bit pattern in a floating-point value is meaningful. **Many** values are rarely used; signaling NaNs are mostly useless in day-to-day programming. But a general purpose library cannot ignore their existence and use them to encode "not-a-value"; that would break the (admittedly rare) code that does use them. – Pete Becker Oct 22 '18 at 13:47

1 Answers1

5

The standard requires that, if you store a value in an std::optional, then the value must be able to be retrieved exactly as stored. Furthermore, if an optional<T> is engaged, you can store any T in the optional's value without letting the optional know you're doing it. Like this:

optional<T> opt = T{};
auto &&val = *opt;
val = <insert value here>; //opt has no idea it has been set.

Because of this, the only valid way optional<T> can be optimized to use certain values of T to mean that the optional is unengaged is if it is impossible for a user to create a T with those values. IEEE-754 implementations of double can assume any bitpattern, and all of them are legal (even signaling NaN).

The reason other optional types can do this is because they have an implicit agreement with the user that they will not set it to certain values. std::optional<T> has no such agreement; any value which T can assume can be stored and retrieved.

Now, if optional<T>::operator* and optional<T>::value returned some kind of proxy object rather than a direct reference to T, then this might be possible, since the proxy could handle appropriate conversions. But even then, the standard would have to specifically state that attempting to set it to one of these values will cause the value to assume an equivalent but different object representation.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 4
    Nitpick: Maybe you could just make one big fat NO as intro to your answer since a lot of people may not be able to follow the answer since it requires some nontrivial knowledge of C++, for example auto&& – NoSenseEtAl Oct 22 '18 at 14:35
  • 2
    @NoSenseEtAl: `auto&&` is something that people are going to need to become [increasingly familiar with](https://stackoverflow.com/q/51461281/734069), so the sooner, the better. Also, it's functionally no different from `auto&` in the case of `optional`. – Nicol Bolas Oct 22 '18 at 14:51
  • 1
    I see your point, but answers should be as narrow as possible IMAO, so that begginers can "get" 1 item at the time... anyway like I said it is a nitpick. Very nice answer, I did not think of this use case for optional – NoSenseEtAl Oct 22 '18 at 15:12