From fdc98d17ca4360e921d3384a4d7210b74646bbd7 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski optional
's default constructor
creates an uninitialized optional. No call to Resource
's
default constructor is attempted. Resource
- doesn't have to be Default
- Constructible. In function getResource
- we first check if resource_
- is initialized. This time we do not use the contextual conversion to bool
, but a comparison with boost::none
. These two ways are equivalent. Function
- emplace
initializes the optional
- in-place by perfect-forwarding the arguments to the constructor of Resource
. No copy- or move-construction
- is involved here. Resource
+ doesn't have to be DefaultConstructible
. In function
+ getResource
we first check
+ if resource_
is initialized.
+ This time we do not use the contextual conversion to bool
,
+ but a comparison with boost::none
.
+ These two ways are equivalent. Function emplace
+ initializes the optional in-place by perfect-forwarding the arguments to
+ the constructor of Resource
.
+ No copy- or move-construction is involved here. Resource
doesn't even have to be MoveConstructible
.
Last revised: June 05, 2014 at 22:46:34 GMT |
+Last revised: June 06, 2014 at 21:22:06 GMT |
![]() |
+Home | +Libraries | +People | +FAQ | +More | +
+// In Header: <
boost/optional/optional.hpp> + +namespace boost { + +template<class T> +class optional +{ + public : + + // (If T is of reference type, the parameters and results by reference are by value) + + optional () noexcept ;+ + optional ( none_t ) noexcept ;
+ + optional ( T const& v ) ;
+ + optional ( T&& v ) ;
+ + // [new in 1.34] + optional ( bool condition, T const& v ) ;
+ + optional ( optional const& rhs ) ;
+ + optional ( optional&& rhs ) noexcept(see below) ;
+ + template<class U> explicit optional ( optional<U> const& rhs ) ;
+ + template<class U> explicit optional ( optional<U>&& rhs ) ;
+ + template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ;
+ + template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
+ + optional& operator = ( none_t ) noexcept ;
+ + optional& operator = ( T const& v ) ;
+ + optional& operator = ( T&& v ) ;
+ + optional& operator = ( optional const& rhs ) ;
+ + optional& operator = ( optional&& rhs ) noexcept(see below) ;
+ + template<class U> optional& operator = ( optional<U> const& rhs ) ;
+ + template<class U> optional& operator = ( optional<U>&& rhs ) ;
+ + template<class... Args> void emplace ( Args...&& args ) ;
+ + template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ;
+ + template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ;
+ + T const& get() const ;
+ T& get() ;
+ + T const* operator ->() const ;
+ T* operator ->() ;
+ + T const& operator *() const& ;
+ T& operator *() &;
+ T&& operator *() &&;
+ + T const& value() const& ;
+ T& value() & ;
+ T&& value() && ;
+ + template<class U> T value_or( U && v ) const& ;
+ template<class U> T value_or( U && v ) && ;
+ + T const* get_ptr() const ;
+ T* get_ptr() ;
+ + explicit operator bool() const ;
+ + bool operator!() const noexcept ;
+ + // deprecated methods + + // (deprecated) + void reset() noexcept ;
+ + // (deprecated) + void reset ( T const& ) ;
+ + // (deprecated) + bool is_initialized() const ;
+ + // (deprecated) + T const& get_value_or( T const& default ) const ;
+}; + +template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ;
+ +template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ;
+ +template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ;
+ +template<class T> inline optional<T> make_optional ( T const& v ) ;
+ +template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ;
+ +template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ;
+ +template<class T> inline T const& get ( optional<T> const& opt ) ;
+ +template<class T> inline T& get ( optional<T> & opt ) ;
+ +template<class T> inline T const* get ( optional<T> const* opt ) ;
+ +template<class T> inline T* get ( optional<T>* opt ) ;
+ +template<class T> inline T const* get_pointer ( optional<T> const& opt ) ;
+ +template<class T> inline T* get_pointer ( optional<T> & opt ) ;
+ +template<class T> inline void swap( optional<T>& x, optional<T>& y ) ;
+ +} // namespace boost +
+ | + |
![]() |
+Home | +Libraries | +People | +FAQ | +More | +
+ Consider these functions which should return a value but which might not + have a value to return: +
+double sqrt(double n );
+ char get_async_input();
+ point polygon::get_any_point_effectively_inside();
+ + There are different approaches to the issue of not having a value to return. +
++ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or + uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the lack + of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply + only parameters in a valid domain for execution to continue normally. +
++ However, function (B), because of its asynchronous nature, does not fail + just because it can't find a value to return; so it is incorrect to consider + such a situation an error and assert or throw an exception. This function + must return, and somehow, must tell the callee that it is not returning a + meaningful value. +
++ A similar situation occurs with function (C): it is conceptually an error + to ask a null-area polygon to return a point inside + itself, but in many applications, it is just impractical for performance + reasons to treat this as an error (because detecting that the polygon has + no area might be too expensive to be required to be tested previously), and + either an arbitrary point (typically at infinity) is returned, or some efficient + way to tell the callee that there is no such point is used. +
+
+ There are various mechanisms to let functions communicate that the returned
+ value is not valid. One such mechanism, which is quite common since it has
+ zero or negligible overhead, is to use a special value which is reserved
+ to communicate this. Classical examples of such special values are EOF
, string::npos
,
+ points at infinity, etc...
+
+ When those values exist, i.e. the return type can hold all meaningful values
+ plus the signal value, this mechanism
+ is quite appropriate and well known. Unfortunately, there are cases when
+ such values do not exist. In these cases, the usual alternative is either
+ to use a wider type, such as int
+ in place of char
; or a compound
+ type, such as std::pair<point,bool>
.
+
+ Returning a std::pair<T,bool>
, thus attaching a boolean flag to the
+ result which indicates if the result is meaningful, has the advantage that
+ can be turned into a consistent idiom since the first element of the pair
+ can be whatever the function would conceptually return. For example, the
+ last two functions could have the following interface:
+
std::pair<char,bool> get_async_input(); +std::pair<point,bool> polygon::get_any_point_effectively_inside(); ++
+ These functions use a consistent interface for dealing with possibly nonexistent + results: +
+std::pair<point,bool> p = poly.get_any_point_effectively_inside(); +if ( p.second ) + flood_fill(p.first); ++
+ However, not only is this quite a burden syntactically, it is also error + prone since the user can easily use the function result (first element of + the pair) without ever checking if it has a valid value. +
++ Clearly, we need a better idiom. +
++ | + |
class Widget { - boost::optional<Resource> resource_; + mutable boost::optional<const Resource> resource_; public: Widget() {} - Resource& getResource() // not thread-safe + const Resource& getResource() const // not thread-safe { if (resource_ == boost::none) resource_.emplace("resource", "arguments"); diff --git a/doc/html/index.html b/doc/html/index.html index f981d82..297e7be 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -129,7 +129,7 @@
Last revised: June 06, 2014 at 21:22:06 GMT |
+Last revised: June 06, 2014 at 21:50:26 GMT |
- The second line works already, this is the capability of Boost.Tuple library,
- but the first line won't work. We could set some invented initial dates,
- but it is confusing and may be an unacceptable cost, given that these values
- will be overwritten in the next line anyway. This is where optional
can help:
+ The second line works already, this is the capability of Boost.Tuple
+ library, but the first line won't work. We could set some invented initial
+ dates, but it is confusing and may be an unacceptable cost, given that these
+ values will be overwritten in the next line anyway. This is where optional
can help:
boost::optional<Date> begin, end; boost::tie(begin, end) = getPeriod(); diff --git a/doc/html/boost_optional/quick_start/storage_in_containers.html b/doc/html/boost_optional/quick_start/storage_in_containers.html index 1715431..f13f5a7 100644 --- a/doc/html/boost_optional/quick_start/storage_in_containers.html +++ b/doc/html/boost_optional/quick_start/storage_in_containers.html @@ -43,14 +43,9 @@
This works because optional<T>
- is LessThanComparable
whenever
- T
is LessThanComparable
.
- In this case the state of being uninitialized is treated as a yet another
- value of T
, which is compared
- less than any value of T
.
- So the set of values that type optional<T>
- can assume is {boost::none
, -2147483648, -2147483647, ..., -1,
- 0, 1, ..., 2147483647} (assuming a 32-bit int
).
+ is LessThanComparable
whenever T
is LessThanComparable
. In this case
+ the state of being uninitialized is treated as a yet another value of T
, which is compared less than any value
+ of T
.