[optional] Suggestion for adding an optional_number class
I'd like to make a suggestion for adding an optional class for number
types, called optional_number, where the max value of the number type is
utilized as the uninitalized value.
Differences compared to std::optional
On 21 July 2017 at 10:47, Viktor Sehr via Boost
I'd like to make a suggestion for adding an optional class for number types, called optional_number, where the max value of the number type is utilized as the uninitalized value.
What problem are you trying to solve?
- Can be assigned to any value except the max value
<snip> - Throws if assigned the numeric_limits<T>::max
Seems to me the poison is worse than the disease. degski -- "*Ihre sogenannte Religion wirkt bloß wie ein Opiat reizend, betäubend, Schmerzen aus Schwäche stillend.*" - Novalis 1798
I'd like to make a suggestion for adding an optional class for number types, called optional_number, where the max value of the number type is utilized as the uninitalized value.
What problem are you trying to solve?
The same problem as boost::optional solves for integers\enums\floats, but without the additional space for a boolean. In the case of numbers programmers often tend to use magic numbers (std::string::npos, -1, less than 0, enum::None) etc to indicate nonexistante index\invalid value etc. Boost::optional solves this but adds a little overhead in space, using an optional_number does not.
- Throws if assigned the numeric_limits<T>::max
Seems to me the poison is worse than the disease.
I expressed myself badly perhaps, what I mean is that users cannot utilize the max value in any way. It's hidden inside the optional, meaning that any handling of the max value is undefined or throws. Perhaps even a static max member function returning (numeric_limits::max<T>() -1) should be added. /Viktor
On 24/07/2017 19:29, Viktor Sehr wrote:
I expressed myself badly perhaps, what I mean is that users cannot utilize the max value in any way. It's hidden inside the optional, meaning that any handling of the max value is undefined or throws. Perhaps even a static max member function returning (numeric_limits::max<T>() -1) should be added.
Memory is cheap; the extra tests required to throw on: optional_number<unsigned> x = 0; --x; (Or the developer headaches that would ensue if made UB and arithmetic operations occasionally make the value pop in and out of existence or do other weird things.) Are less cheap. If you're worried about wasting memory in large arrays of numbers, consider a hybrid approach where you have an array of regular integers and a bitset that separately indicates validity. This might use an extra cache line but still should perform reasonably well.
On 21.07.2017 10:47, Viktor Sehr via Boost wrote:
I'd like to make a suggestion for adding an optional class for number types, called optional_number, where the max value of the number type is utilized as the uninitalized value.
Differences compared to std::optional
: *- No size overhead from the wrapped type* - Theoretically faster (althrough in practice probably negilble) - Can be assigned to any value except the max value - Operator-> is removed as it does not make sense for an integer Notes: - Throws if assigned the numeric_limits<T>::max - Also works with enums, using the underlying_type - The operator bool conversion is missing in the prototype implementation
Attaching a prototype implementation (currently for C++14).
/Viktor
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hello, FYI there was a proposal recently for optional with the same purpose; unfortunately, it went nowhere: https://lists.boost.org/Archives/boost/2015/09/225692.php Though I think that a most valuable rationale for it is this special optional being a tool for wrapping legacy code or systems that already utilize special value idiom. Also, throw on special value assignment is insane - it might be perfectly fine to pass special values to indicate something other than error - say, in a system it might be defined as a missing value (e.g. NaN meaning n/a). Or a completely different thing - special value as a non-error, everything else as an error; it may add usability to thin wrappers to legacy API. -------- Mitsyn Sergey
On 25 July 2017 at 16:46, Sergey Mitsyn via Boost
Also, throw on special value assignment is insane
+1
- it might be perfectly fine to pass special values to indicate something other than error - say, in a system it might be defined as a missing value (e.g. NaN meaning n/a).
And checking the that totally normal (and informative, could be a value in an enum class) return value directly is just as easy (or easier and more clear) than to have to write a try/catch block. degski -- "*Ihre sogenannte Religion wirkt bloß wie ein Opiat reizend, betäubend, Schmerzen aus Schwäche stillend.*" - Novalis 1798
On 25. Jul 2017, at 15:46, Sergey Mitsyn via Boost
wrote: FYI there was a proposal recently for optional with the same purpose; unfortunately, it went nowhere:
There was also boost::markable with a similar intend: https://lists.boost.org/Archives/boost/2016/09/230811.php
Thanks for your critique, as I see boost::markable is exactly what I was intended as it is a little bit more generalized. Regarding the throwing, I intended the throw when assigned the mark value to be an "equivalent" to a assert, as I imagined the intention of assigning an uninitalized value is more clear if forced to used "val = {}" or "val.reset();", meaning it would be more of a drop-in replacement for boost::optional. /Viktor On Wed, Jul 26, 2017 at 1:41 PM Hans Dembinski via Boost < boost@lists.boost.org> wrote:
On 25. Jul 2017, at 15:46, Sergey Mitsyn via Boost < boost@lists.boost.org> wrote:
FYI there was a proposal recently for optional with the same purpose; unfortunately, it went nowhere:
There was also boost::markable with a similar intend: https://lists.boost.org/Archives/boost/2016/09/230811.php
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 26. Jul 2017, at 15:07, Viktor Sehr
wrote: Thanks for your critique, as I see boost::markable is exactly what I was intended as it is a little bit more generalized.
Regarding the throwing, I intended the throw when assigned the mark value to be an "equivalent" to a assert, as I imagined the intention of assigning an uninitalized value is more clear if forced to used "val = {}" or "val.reset();", meaning it would be more of a drop-in replacement for boost::optional.
For what it's worth, I don't understand the critique in this thread. I thought that boost::markable was a neat idea and since people already use special integer values to indicate errors already, see std::string::npos, why not make a nice template for this use case that makes this (mis)use of special integer values more obvious and less error prone.
participants (5)
-
degski
-
Gavin Lambert
-
Hans Dembinski
-
Sergey Mitsyn
-
Viktor Sehr