From a3b478b6209b40b1e467b7e6bc5907efb3783a18 Mon Sep 17 00:00:00 2001
From: Daniel James
Date: Sat, 12 Apr 2014 09:10:24 +0100
Subject: [PATCH 01/18] Use super-project's css file.
---
doc/Jamfile.v2 | 2 +-
doc/html/boostbook.css | 582 -----------------------------------------
2 files changed, 1 insertion(+), 583 deletions(-)
delete mode 100755 doc/html/boostbook.css
diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2
index 93998d0..95de749 100644
--- a/doc/Jamfile.v2
+++ b/doc/Jamfile.v2
@@ -10,6 +10,7 @@
# Quickbook
# -----------------------------------------------------------------------------
+using boostbook ;
import quickbook ;
path-constant images : html ;
@@ -24,7 +25,6 @@ boostbook standalone
optional
:
boost.root=../../../..
- html.stylesheet=boostbook.css
toc.max.depth=2
toc.section.depth=2
chunk.section.depth=1
diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css
deleted file mode 100755
index e5d7bb5..0000000
--- a/doc/html/boostbook.css
+++ /dev/null
@@ -1,582 +0,0 @@
-/*=============================================================================
- Copyright (c) 2004 Joel de Guzman
- http://spirit.sourceforge.net/
-
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
-=============================================================================*/
-
-/*=============================================================================
- Body defaults
-=============================================================================*/
-
- body
- {
- margin: 1em;
- font-family: sans-serif;
- }
-
-/*=============================================================================
- Paragraphs
-=============================================================================*/
-
- p
- {
- text-align: left;
- font-size: 10pt;
- line-height: 1.15;
- }
-
-/*=============================================================================
- Program listings
-=============================================================================*/
-
- /* Code on paragraphs */
- p tt.computeroutput
- {
- font-size: 10pt;
- }
-
- pre.synopsis
- {
- font-size: 10pt;
- margin: 1pc 4% 0pc 4%;
- padding: 0.5pc 0.5pc 0.5pc 0.5pc;
- }
-
- .programlisting,
- .screen
- {
- font-size: 10pt;
- display: block;
- margin: 1pc 4% 0pc 4%;
- padding: 0.5pc 0.5pc 0.5pc 0.5pc;
- }
-
- /* Program listings in tables don't get borders */
- td .programlisting,
- td .screen
- {
- margin: 0pc 0pc 0pc 0pc;
- padding: 0pc 0pc 0pc 0pc;
- }
-
-/*=============================================================================
- Headings
-=============================================================================*/
-
- h1, h2, h3, h4, h5, h6
- {
- text-align: left;
- margin: 1em 0em 0.5em 0em;
- font-weight: bold;
- }
-
- h1 { font: 140% }
- h2 { font: bold 140% }
- h3 { font: bold 130% }
- h4 { font: bold 120% }
- h5 { font: italic 110% }
- h6 { font: italic 100% }
-
- /* Top page titles */
- title,
- h1.title,
- h2.title
- h3.title,
- h4.title,
- h5.title,
- h6.title,
- .refentrytitle
- {
- font-weight: bold;
- margin-bottom: 1pc;
- }
-
- h1.title { font-size: 140% }
- h2.title { font-size: 140% }
- h3.title { font-size: 130% }
- h4.title { font-size: 120% }
- h5.title { font-size: 110% }
- h6.title { font-size: 100% }
-
- .section h1
- {
- margin: 0em 0em 0.5em 0em;
- font-size: 140%;
- }
-
- .section h2 { font-size: 140% }
- .section h3 { font-size: 130% }
- .section h4 { font-size: 120% }
- .section h5 { font-size: 110% }
- .section h6 { font-size: 100% }
-
- /* Code on titles */
- h1 tt.computeroutput { font-size: 140% }
- h2 tt.computeroutput { font-size: 140% }
- h3 tt.computeroutput { font-size: 130% }
- h4 tt.computeroutput { font-size: 120% }
- h5 tt.computeroutput { font-size: 110% }
- h6 tt.computeroutput { font-size: 100% }
-
-/*=============================================================================
- Author
-=============================================================================*/
-
- h3.author
- {
- font-size: 100%
- }
-
-/*=============================================================================
- Lists
-=============================================================================*/
-
- li
- {
- font-size: 10pt;
- line-height: 1.3;
- }
-
- /* Unordered lists */
- ul
- {
- text-align: left;
- }
-
- /* Ordered lists */
- ol
- {
- text-align: left;
- }
-
-/*=============================================================================
- Links
-=============================================================================*/
-
- a
- {
- text-decoration: none; /* no underline */
- }
-
- a:hover
- {
- text-decoration: underline;
- }
-
-/*=============================================================================
- Spirit style navigation
-=============================================================================*/
-
- .spirit-nav
- {
- text-align: right;
- }
-
- .spirit-nav a
- {
- color: white;
- padding-left: 0.5em;
- }
-
- .spirit-nav img
- {
- border-width: 0px;
- }
-
-/*=============================================================================
- Table of contents
-=============================================================================*/
-
- .toc
- {
- margin: 1pc 4% 0pc 4%;
- padding: 0.1pc 1pc 0.1pc 1pc;
- font-size: 10pt;
- line-height: 1.15;
- }
-
- .toc-main
- {
- text-align: center;
- margin: 3pc 16% 3pc 16%;
- padding: 3pc 1pc 3pc 1pc;
- line-height: 0.1;
- }
-
- .boost-toc
- {
- float: right;
- padding: 0.5pc;
- }
-
-/*=============================================================================
- Tables
-=============================================================================*/
-
- .table-title,
- div.table p.title
- {
- margin-left: 4%;
- padding-right: 0.5em;
- padding-left: 0.5em;
- }
-
- .informaltable table,
- .table table
- {
- width: 92%;
- margin-left: 4%;
- margin-right: 4%;
- }
-
- div.informaltable table,
- div.table table
- {
- padding: 4px;
- }
-
- /* Table Cells */
- div.informaltable table tr td,
- div.table table tr td
- {
- padding: 0.5em;
- text-align: left;
- }
-
- div.informaltable table tr th,
- div.table table tr th
- {
- padding: 0.5em 0.5em 0.5em 0.5em;
- border: 1pt solid white;
- font-size: 120%;
- }
-
-/*=============================================================================
- Blurbs
-=============================================================================*/
-
- div.note,
- div.tip,
- div.important,
- div.caution,
- div.warning,
- div.sidebar
- {
- font-size: 10pt;
- line-height: 1.2;
- display: block;
- margin: 1pc 4% 0pc 4%;
- padding: 0.5pc 0.5pc 0.5pc 0.5pc;
- }
-
- div.sidebar img
- {
- padding: 1pt;
- }
-
-
-
-/*=============================================================================
- Callouts
-=============================================================================*/
- .line_callout_bug img
- {
- float: left;
- position:relative;
- left: 4px;
- top: -12px;
- clear: left;
- margin-left:-22px;
- }
-
- .callout_bug img
- {
- }
-
-
-
-/*=============================================================================
- Variable Lists
-=============================================================================*/
-
- /* Make the terms in definition lists bold */
- div.variablelist dl dt,
- span.term
- {
- font-weight: bold;
- font-size: 10pt;
- }
-
- div.variablelist table tbody tr td
- {
- text-align: left;
- vertical-align: top;
- padding: 0em 2em 0em 0em;
- font-size: 10pt;
- margin: 0em 0em 0.5em 0em;
- line-height: 1;
- }
-
- /* Make the terms in definition lists bold */
- div.variablelist dl dt
- {
- margin-bottom: 0.2em;
- }
-
- div.variablelist dl dd
- {
- margin: 0em 0em 0.5em 2em;
- font-size: 10pt;
- }
-
- div.variablelist table tbody tr td p
- div.variablelist dl dd p
- {
- margin: 0em 0em 0.5em 0em;
- line-height: 1;
- }
-
-/*=============================================================================
- Misc
-=============================================================================*/
-
- /* Title of books and articles in bibliographies */
- span.title
- {
- font-style: italic;
- }
-
- span.underline
- {
- text-decoration: underline;
- }
-
- span.strikethrough
- {
- text-decoration: line-through;
- }
-
- /* Copyright, Legal Notice */
- div div.legalnotice p
- {
- text-align: left
- }
-
-/*=============================================================================
- Colors
-=============================================================================*/
-
- @media screen
- {
- /* Links */
- a
- {
- color: #0C7445;
- }
-
- a:visited
- {
- color: #663974;
- }
-
- h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
- h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
- h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
- {
- text-decoration: none; /* no underline */
- color: #000000;
- }
-
- /* Syntax Highlighting */
- .keyword { color: #0000AA; }
- .identifier { color: #000000; }
- .special { color: #707070; }
- .preprocessor { color: #402080; }
- .char { color: teal; }
- .comment { color: #800000; }
- .string { color: teal; }
- .number { color: teal; }
- .white_bkd { background-color: #E8FBE9; }
- .dk_grey_bkd { background-color: #A0DAAC; }
-
- /* Copyright, Legal Notice */
- .copyright
- {
- color: #666666;
- font-size: small;
- }
-
- div div.legalnotice p
- {
- color: #666666;
- }
-
- /* Program listing */
- pre.synopsis
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- .programlisting,
- .screen
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- td .programlisting,
- td .screen
- {
- border: 0px solid #DCDCDC;
- }
-
- /* Blurbs */
- div.note,
- div.tip,
- div.important,
- div.caution,
- div.warning,
- div.sidebar
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- /* Table of contents */
- .toc
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- /* Table of contents */
- .toc-main
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
-
- /* Tables */
- div.informaltable table tr td,
- div.table table tr td
- {
- border: 1px solid #DCDCDC;
- background-color: #FAFFFB;
- }
-
- div.informaltable table tr th,
- div.table table tr th
- {
- background-color: #E3F9E4;
- border: 1px solid #DCDCDC;
- }
-
- /* Misc */
- span.highlight
- {
- color: #00A000;
- }
- }
-
- @media print
- {
- /* Links */
- a
- {
- color: black;
- }
-
- a:visited
- {
- color: black;
- }
-
- .spirit-nav
- {
- display: none;
- }
-
- /* Program listing */
- pre.synopsis
- {
- border: 1px solid gray;
- background-color: #FAFFFB;
- }
-
- .programlisting,
- .screen
- {
- border: 1px solid gray;
- background-color: #FAFFFB;
- }
-
- td .programlisting,
- td .screen
- {
- border: 0px solid #DCDCDC;
- }
-
- /* Table of contents */
- .toc
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- /* Table of contents */
- .toc-main
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- background-color: #FAFFFB;
- }
-
- .informaltable table,
- .table table
- {
- border: 1px solid #DCDCDC;
- border-bottom: 3px solid #9D9D9D;
- border-right: 3px solid #9D9D9D;
- border-collapse: collapse;
- background-color: #FAFFFB;
- }
-
- /* Tables */
- div.informaltable table tr td,
- div.table table tr td
- {
- border: 1px solid #DCDCDC;
- background-color: #FAFFFB;
- }
-
- div.informaltable table tr th,
- div.table table tr th
- {
- border: 1px solid #DCDCDC;
- background-color: #FAFFFB;
- }
-
- /* Misc */
- span.highlight
- {
- font-weight: bold;
- }
- }
From b4738ac07ecb8644f1de40ea2d07193a4ca50ce1 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Sat, 12 Apr 2014 20:54:37 +0200
Subject: [PATCH 02/18] Updated HTML documentation format using the
super-project css and docbook-xsl-1.78.1
---
doc/html/HTML.manifest | 14 --------------
.../a_note_about_optional_bool_.html | 4 ++--
doc/html/boost_optional/acknowledgments.html | 4 ++--
.../dependencies_and_portability.html | 4 ++--
doc/html/boost_optional/detailed_semantics.html | 4 ++--
doc/html/boost_optional/development.html | 6 +++---
doc/html/boost_optional/examples.html | 6 +++---
.../exception_safety_guarantees.html | 4 ++--
doc/html/boost_optional/implementation_notes.html | 4 ++--
doc/html/boost_optional/in_place_factories.html | 4 ++--
doc/html/boost_optional/optional_references.html | 4 ++--
...tics_for_assignment_of_optional_references.html | 4 ++--
doc/html/boost_optional/synopsis.html | 4 ++--
doc/html/boost_optional/type_requirements.html | 4 ++--
doc/html/index.html | 6 +++---
15 files changed, 31 insertions(+), 45 deletions(-)
delete mode 100644 doc/html/HTML.manifest
diff --git a/doc/html/HTML.manifest b/doc/html/HTML.manifest
deleted file mode 100644
index 759b268..0000000
--- a/doc/html/HTML.manifest
+++ /dev/null
@@ -1,14 +0,0 @@
-index.html
-boost_optional/development.html
-boost_optional/synopsis.html
-boost_optional/detailed_semantics.html
-boost_optional/examples.html
-boost_optional/optional_references.html
-boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
-boost_optional/in_place_factories.html
-boost_optional/a_note_about_optional_bool_.html
-boost_optional/exception_safety_guarantees.html
-boost_optional/type_requirements.html
-boost_optional/implementation_notes.html
-boost_optional/dependencies_and_portability.html
-boost_optional/acknowledgments.html
diff --git a/doc/html/boost_optional/a_note_about_optional_bool_.html b/doc/html/boost_optional/a_note_about_optional_bool_.html
index 8d70d49..c9f3a78 100644
--- a/doc/html/boost_optional/a_note_about_optional_bool_.html
+++ b/doc/html/boost_optional/a_note_about_optional_bool_.html
@@ -2,8 +2,8 @@
A note about optional<bool>
-
-
+
+
diff --git a/doc/html/boost_optional/acknowledgments.html b/doc/html/boost_optional/acknowledgments.html
index d56c25c..6ae8176 100644
--- a/doc/html/boost_optional/acknowledgments.html
+++ b/doc/html/boost_optional/acknowledgments.html
@@ -2,8 +2,8 @@
Acknowledgments
-
-
+
+
diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html
index 6fa31dd..928f4bd 100644
--- a/doc/html/boost_optional/dependencies_and_portability.html
+++ b/doc/html/boost_optional/dependencies_and_portability.html
@@ -2,8 +2,8 @@
Dependencies and Portability
-
-
+
+
diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html
index 9f8b56b..4ab1a29 100644
--- a/doc/html/boost_optional/detailed_semantics.html
+++ b/doc/html/boost_optional/detailed_semantics.html
@@ -2,8 +2,8 @@
Detailed Semantics
-
-
+
+
diff --git a/doc/html/boost_optional/development.html b/doc/html/boost_optional/development.html
index 7f21580..9cc75e8 100644
--- a/doc/html/boost_optional/development.html
+++ b/doc/html/boost_optional/development.html
@@ -2,8 +2,8 @@
Development
-
-
+
+
@@ -26,7 +26,7 @@
-
+
The models
The semantics
The Interface
diff --git a/doc/html/boost_optional/examples.html b/doc/html/boost_optional/examples.html
index 54c3953..ad0e02f 100644
--- a/doc/html/boost_optional/examples.html
+++ b/doc/html/boost_optional/examples.html
@@ -2,8 +2,8 @@
Examples
-
-
+
+
@@ -26,7 +26,7 @@
-
+
Optional
return values
Optional
diff --git a/doc/html/boost_optional/exception_safety_guarantees.html b/doc/html/boost_optional/exception_safety_guarantees.html
index 4ffa059..09d7766 100644
--- a/doc/html/boost_optional/exception_safety_guarantees.html
+++ b/doc/html/boost_optional/exception_safety_guarantees.html
@@ -2,8 +2,8 @@
Exception Safety Guarantees
-
-
+
+
diff --git a/doc/html/boost_optional/implementation_notes.html b/doc/html/boost_optional/implementation_notes.html
index fdec333..cfa2fad 100644
--- a/doc/html/boost_optional/implementation_notes.html
+++ b/doc/html/boost_optional/implementation_notes.html
@@ -2,8 +2,8 @@
Implementation Notes
-
-
+
+
diff --git a/doc/html/boost_optional/in_place_factories.html b/doc/html/boost_optional/in_place_factories.html
index b13dcdf..ec7e39d 100644
--- a/doc/html/boost_optional/in_place_factories.html
+++ b/doc/html/boost_optional/in_place_factories.html
@@ -2,8 +2,8 @@
In-Place Factories
-
-
+
+
diff --git a/doc/html/boost_optional/optional_references.html b/doc/html/boost_optional/optional_references.html
index c6ad1e1..a603c1c 100644
--- a/doc/html/boost_optional/optional_references.html
+++ b/doc/html/boost_optional/optional_references.html
@@ -2,8 +2,8 @@
Optional references
-
-
+
+
diff --git a/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html b/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
index e9b21a4..6dbac4d 100644
--- a/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
+++ b/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
@@ -2,8 +2,8 @@
Rebinding semantics for assignment of optional references
-
-
+
+
diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html
index ca3c1b6..078dd02 100644
--- a/doc/html/boost_optional/synopsis.html
+++ b/doc/html/boost_optional/synopsis.html
@@ -2,8 +2,8 @@
Synopsis
-
-
+
+
diff --git a/doc/html/boost_optional/type_requirements.html b/doc/html/boost_optional/type_requirements.html
index e148299..9723c4c 100644
--- a/doc/html/boost_optional/type_requirements.html
+++ b/doc/html/boost_optional/type_requirements.html
@@ -2,8 +2,8 @@
Type requirements
-
-
+
+
diff --git a/doc/html/index.html b/doc/html/index.html
index 12803e7..2103f59 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -2,8 +2,8 @@
Chapter 1. Boost.Optional
-
-
+
+
@@ -35,7 +35,7 @@
Table of Contents
-
+
Motivation
Development
From 587ef8e9889d4f597890bc78a8debe889b0dd0d3 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Mon, 14 Apr 2014 23:44:34 +0200
Subject: [PATCH 03/18] Added 'raw' move semantics; no unit-tests
---
include/boost/optional/optional.hpp | 137 ++++++++++++++++++++++++++--
1 file changed, 128 insertions(+), 9 deletions(-)
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index 603facd..4ae36f0 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -131,6 +131,9 @@ struct types_when_isnt_ref
{
typedef T const& reference_const_type ;
typedef T & reference_type ;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef T && rval_reference_type ;
+#endif
typedef T const* pointer_const_type ;
typedef T * pointer_type ;
typedef T const& argument_type ;
@@ -140,11 +143,14 @@ struct types_when_is_ref
{
typedef BOOST_DEDUCED_TYPENAME remove_reference::type raw_type ;
- typedef raw_type& reference_const_type ;
- typedef raw_type& reference_type ;
- typedef raw_type* pointer_const_type ;
- typedef raw_type* pointer_type ;
- typedef raw_type& argument_type ;
+ typedef raw_type& reference_const_type ;
+ typedef raw_type& reference_type ;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef raw_type&& rval_reference_type ;
+#endif
+ typedef raw_type* pointer_const_type ;
+ typedef raw_type* pointer_type ;
+ typedef raw_type& argument_type ;
} ;
struct optional_tag {} ;
@@ -184,6 +190,9 @@ class optional_base : public optional_tag
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
+#endif
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
@@ -209,6 +218,17 @@ class optional_base : public optional_tag
construct(val);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // move-construct an optional initialized from an rvalue-ref to 'val'.
+ // Can throw if T::T(T&&) does
+ optional_base ( rval_reference_type val )
+ :
+ m_initialized(false)
+ {
+ construct( static_cast(val) );
+ }
+#endif
+
// Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
@@ -229,6 +249,17 @@ class optional_base : public optional_tag
construct(rhs.get_impl());
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Creates a deep move of another optional
+ // Can throw if T::T(T&&) does
+ optional_base ( optional_base&& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct( static_cast(rhs.get_impl()) );
+ }
+#endif
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
@@ -279,6 +310,26 @@ class optional_base : public optional_tag
}
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // move-assigns from another _convertible_ optional (deep-moves from the rhs value)
+ template
+ void assign ( optional&& rhs )
+ {
+ typedef BOOST_DEDUCED_TYPENAME optional::rval_reference_type ref_type;
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(static_cast(rhs.get()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(static_cast(rhs.get()));
+ }
+ }
+#endif
+
// Assigns from a T (deep-copies the rhs value)
void assign ( argument_type val )
{
@@ -286,6 +337,16 @@ class optional_base : public optional_tag
assign_value(val, is_reference_predicate() );
else construct(val);
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ void assign ( rval_reference_type val )
+ {
+ if (is_initialized())
+ assign_value( static_cast(val), is_reference_predicate() );
+ else construct( static_cast(val) );
+ }
+#endif
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
@@ -325,6 +386,14 @@ class optional_base : public optional_tag
new (m_storage.address()) internal_type(val) ;
m_initialized = true ;
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void construct ( rval_reference_type val )
+ {
+ new (m_storage.address()) internal_type( static_cast(val) ) ;
+ m_initialized = true ;
+ }
+#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Constructs in-place using the given factory
@@ -411,6 +480,10 @@ class optional_base : public optional_tag
void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast(val); }
+ void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast(val) ); }
+#endif
void destroy()
{
@@ -488,22 +561,34 @@ class optional : public optional_detail::optional_base
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
+#endif
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional uninitialized.
// No-throw
- optional() : base() {}
+ optional() BOOST_NOEXCEPT : base() {}
// Creates an optional uninitialized.
// No-throw
- optional( none_t none_ ) : base(none_) {}
+ optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
// Creates an optional initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Creates an optional initialized with 'move(val)'.
+ // Can throw if T::T(T &&) does
+ optional ( rval_reference_type val ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(val))))
+ :
+ base( static_cast(val) )
+ {}
+#endif
+
// Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
@@ -521,6 +606,20 @@ class optional : public optional_detail::optional_base
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Creates a deep move of another convertible optional
+ // Requires a valid conversion from U to T.
+ // Can throw if T::T(U&&) does
+ template
+ explicit optional ( optional && rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct( static_cast::rval_reference_type>(rhs.get()) );
+ }
+#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional with an expression which can be either
@@ -573,6 +672,16 @@ class optional : public optional_detail::optional_base
return *this ;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from another optional (deep-moves the rhs value)
+ optional& operator= ( optional && rhs )
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*rhs))) && BOOST_NOEXCEPT_EXPR(*rhs = static_cast(*rhs)))
+ {
+ this->assign( static_cast(rhs) ) ;
+ return *this ;
+ }
+#endif
+
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
@@ -581,6 +690,15 @@ class optional : public optional_detail::optional_base
return *this ;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ optional& operator= ( rval_reference_type val )
+ {
+ this->assign( static_cast(val) ) ;
+ return *this ;
+ }
+#endif
+
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
@@ -591,10 +709,10 @@ class optional : public optional_detail::optional_base
}
void swap( optional & arg )
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*arg))) && BOOST_NOEXCEPT_EXPR(*arg = static_cast(*arg)))
{
// allow for Koenig lookup
- using boost::swap;
- swap(*this, arg);
+ boost::swap(*this, arg);
}
@@ -961,6 +1079,7 @@ template
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ;
template inline void swap ( optional& x, optional& y )
+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*x))) && BOOST_NOEXCEPT_EXPR(*y = static_cast(*x)))
{
optional_detail::swap_selector::value>::optional_swap(x, y);
}
From a26d11be8767f4e32974cb71fbd8aa071b19beaf Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Tue, 22 Apr 2014 22:36:19 +0200
Subject: [PATCH 04/18] Partially added move semantics (tests are still
failing)
---
include/boost/optional/optional.hpp | 157 ++++++++++++---
include/boost/optional/optional_fwd.hpp | 10 +-
test/Jamfile.v2 | 25 +--
test/optional_test_move.cpp | 254 ++++++++++++++++++++++++
4 files changed, 404 insertions(+), 42 deletions(-)
create mode 100644 test/optional_test_move.cpp
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index 4ae36f0..c063e94 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -26,7 +26,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -36,6 +38,8 @@
#include
#include
#include
+#include
+#include
#include
@@ -91,7 +95,8 @@ class in_place_factory_base ;
class typed_in_place_factory_base ;
// This forward is needed to refer to namespace scope swap from the member swap
-template void swap ( optional& x, optional& y );
+template void swap ( optional& x, optional& y )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value);
namespace optional_detail {
@@ -225,7 +230,7 @@ class optional_base : public optional_tag
:
m_initialized(false)
{
- construct( static_cast(val) );
+ construct( boost::move(val) );
}
#endif
@@ -257,10 +262,21 @@ class optional_base : public optional_tag
m_initialized(false)
{
if ( rhs.is_initialized() )
- construct( static_cast(rhs.get_impl()) );
+ construct( boost::move(rhs.get_impl()) );
}
#endif
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template
+ explicit optional_base ( Expr&& expr, PtrExpr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(boost::forward(expr),tag);
+ }
+
+#else
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
// implementation (the correct 'construct()' overload)
@@ -272,6 +288,7 @@ class optional_base : public optional_tag
construct(expr,tag);
}
+#endif
// No-throw (assuming T::~T() doesn't)
@@ -338,13 +355,13 @@ class optional_base : public optional_tag
else construct(val);
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
void assign ( rval_reference_type val )
{
if (is_initialized())
- assign_value( static_cast(val), is_reference_predicate() );
- else construct( static_cast(val) );
+ assign_value( boost::move(val), is_reference_predicate() );
+ else construct( boost::move(val) );
}
#endif
@@ -353,13 +370,25 @@ class optional_base : public optional_tag
void assign ( none_t ) { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template
+ void assign_expr ( Expr&& expr, ExprPtr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(boost::forward(expr),tag);
+ else construct(boost::forward(expr),tag);
+ }
+#else
template
void assign_expr ( Expr const& expr, Expr const* tag )
- {
- if (is_initialized())
- assign_expr_to_initialized(expr,tag);
- else construct(expr,tag);
- }
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(expr,tag);
+ else construct(expr,tag);
+ }
+#endif
+
#endif
public :
@@ -390,7 +419,7 @@ class optional_base : public optional_tag
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void construct ( rval_reference_type val )
{
- new (m_storage.address()) internal_type( static_cast(val) ) ;
+ new (m_storage.address()) internal_type( boost::move(val) ) ;
m_initialized = true ;
}
#endif
@@ -430,7 +459,29 @@ class optional_base : public optional_tag
}
#endif
- // Constructs using any expression implicitely convertible to the single argument
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Constructs using any expression implicitly convertible to the single argument
+ // of a one-argument T constructor.
+ // Converting constructions of optional from optional uses this function with
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template
+ void construct ( Expr&& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(boost::forward(expr)) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional from optional uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template
+ void assign_expr_to_initialized ( Expr&& expr, void const* )
+ {
+ assign_value(boost::forward(expr), is_reference_predicate());
+ }
+#else
+ // Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional from optional uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
@@ -441,7 +492,7 @@ class optional_base : public optional_tag
m_initialized = true ;
}
- // Assigns using a form any expression implicitely convertible to the single argument
+ // Assigns using a form any expression implicitly convertible to the single argument
// of a T's assignment operator.
// Converting assignments of optional from optional uses this function with
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
@@ -451,6 +502,8 @@ class optional_base : public optional_tag
assign_value(expr, is_reference_predicate());
}
+#endif
+
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
// BCB5.64 (and probably lower versions) workaround.
// The in-place factories are supported by means of catch-all constructors
@@ -583,10 +636,7 @@ class optional : public optional_detail::optional_base
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates an optional initialized with 'move(val)'.
// Can throw if T::T(T &&) does
- optional ( rval_reference_type val ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(val))))
- :
- base( static_cast(val) )
- {}
+ optional ( rval_reference_type val ) : base( boost::forward(val) ) {}
#endif
// Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
@@ -617,7 +667,7 @@ class optional : public optional_detail::optional_base
base()
{
if ( rhs.is_initialized() )
- this->construct( static_cast::rval_reference_type>(rhs.get()) );
+ this->construct( boost::move(rhs.get()) );
}
#endif
@@ -625,32 +675,75 @@ class optional : public optional_detail::optional_base
// Creates an optional with an expression which can be either
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
// (b) An instance of TypedInPlaceFactory ( i.e. in_place(a,b,...,n);
- // (c) Any expression implicitely convertible to the single type
+ // (c) Any expression implicitly convertible to the single type
// of a one-argument T's constructor.
// (d*) Weak compilers (BCB) might also resolved Expr as optional and optional
// even though explicit overloads are present for these.
// Depending on the above some T ctor is called.
- // Can throw is the resolved T ctor throws.
+ // Can throw if the resolved T ctor throws.
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#ifndef BOOST_NO_SFINAE
+#else
+ template
+ explicit optional ( Expr&& expr, typename boost::disable_if::type, optional> >::type* = 0 )
+ : base(boost::forward(expr),boost::addressof(expr)) {}
+#endif
+#else
template
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
+#endif
#endif
// Creates a deep copy of another optional
// Can throw if T::T(T const&) does
optional ( optional const& rhs ) : base( static_cast (rhs) ) {}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Creates a deep move of another optional
+ // Can throw if T::T(T&&) does
+ optional ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value)
+ : base( boost::move(rhs) )
+ {}
+
+#ifdef BOOST_NO_SFINAE
+ // To avoid too perfect forwarding
+ optional ( optional& rhs ) : base( static_cast (rhs) ) {}
+#endif
+
+#endif
// No-throw (assuming T::~T() doesn't)
~optional() {}
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template
+#if !defined BOOST_NO_SFINAE
+ typename boost::disable_if<
+ boost::is_same::type, optional>,
+ optional&
+ >::type
+#else
+ optional&
+#endif
+ operator= ( Expr&& expr )
+ {
+ this->assign_expr(boost::forward(expr),boost::addressof(expr));
+ return *this ;
+ }
+
+#else
template
optional& operator= ( Expr const& expr )
{
this->assign_expr(expr,boost::addressof(expr));
return *this ;
}
+#endif
#endif
// Assigns from another convertible optional (converts && deep-copies the rhs value)
@@ -675,11 +768,19 @@ class optional : public optional_detail::optional_base
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from another optional (deep-moves the rhs value)
optional& operator= ( optional && rhs )
- BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*rhs))) && BOOST_NOEXCEPT_EXPR(*rhs = static_cast(*rhs)))
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value)
{
- this->assign( static_cast(rhs) ) ;
+ this->assign( static_cast (rhs) ) ;
return *this ;
}
+#ifdef BOOST_NO_SFINAE
+ // to avoid too perfect forwarding
+ optional& operator= ( optional& rhs )
+ {
+ this->assign( static_cast (rhs) ) ;
+ return *this ;
+ }
+#endif
#endif
// Assigns from a T (deep-copies the rhs value)
@@ -694,7 +795,7 @@ class optional : public optional_detail::optional_base
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
{
- this->assign( static_cast(val) ) ;
+ this->assign( boost::move(val) ) ;
return *this ;
}
#endif
@@ -709,7 +810,7 @@ class optional : public optional_detail::optional_base
}
void swap( optional & arg )
- BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*arg))) && BOOST_NOEXCEPT_EXPR(*arg = static_cast(*arg)))
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value)
{
// allow for Koenig lookup
boost::swap(*this, arg);
@@ -740,11 +841,11 @@ class optional : public optional_detail::optional_base
// implicit conversion to "bool"
// No-throw
- operator unspecified_bool_type() const { return this->safe_bool() ; }
+ operator unspecified_bool_type() const BOOST_NOEXCEPT { return this->safe_bool() ; }
// This is provided for those compilers which don't like the conversion to bool
// on some contexts.
- bool operator!() const { return !this->is_initialized() ; }
+ bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
} ;
// Returns optional(v)
@@ -1079,7 +1180,7 @@ template
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ;
template inline void swap ( optional& x, optional& y )
- BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast(*x))) && BOOST_NOEXCEPT_EXPR(*y = static_cast(*x)))
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value)
{
optional_detail::swap_selector::value>::optional_swap(x, y);
}
diff --git a/include/boost/optional/optional_fwd.hpp b/include/boost/optional/optional_fwd.hpp
index 388cc1c..ade503d 100644
--- a/include/boost/optional/optional_fwd.hpp
+++ b/include/boost/optional/optional_fwd.hpp
@@ -11,15 +11,21 @@
//
// Revisions:
// 10 May 2008 (added swap related forward declaration) Niels Dekker
-//
+// 17 Apr 2014 (added noexcept) Andrzej Krzemienski
+//
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
+#include
+#include
+#include
+
namespace boost {
template class optional ;
-template void swap ( optional& , optional& ) ;
+template void swap ( optional& , optional& )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value);
template struct optional_swap_should_use_default_constructor ;
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 16d4f3c..62ab883 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -17,17 +17,18 @@ import testing ;
{
test-suite optional :
[ run optional_test.cpp ]
- [ run optional_test_tie.cpp ]
- [ run optional_test_ref.cpp ]
- [ run optional_test_inplace.cpp ]
- [ run optional_test_io.cpp ]
- [ compile-fail optional_test_fail1.cpp ]
- [ compile-fail optional_test_fail3a.cpp ]
- [ compile-fail optional_test_fail3b.cpp ]
- [ compile-fail optional_test_ref_fail1.cpp ]
- [ compile-fail optional_test_ref_fail3.cpp ]
- [ compile-fail optional_test_ref_fail4.cpp ]
- [ compile-fail optional_test_inplace_fail.cpp ]
- [ compile-fail optional_test_inplace_fail2.cpp ]
+ #[ run optional_test_tie.cpp ]
+ #[ run optional_test_ref.cpp ]
+ #[ run optional_test_inplace.cpp ]
+ #[ run optional_test_io.cpp ]
+ [ run optional_test_move.cpp ]
+ #[ compile-fail optional_test_fail1.cpp ]
+ #[ compile-fail optional_test_fail3a.cpp ]
+ #[ compile-fail optional_test_fail3b.cpp ]
+ #[ compile-fail optional_test_ref_fail1.cpp ]
+ #[ compile-fail optional_test_ref_fail3.cpp ]
+ #[ compile-fail optional_test_ref_fail4.cpp ]
+ #[ compile-fail optional_test_inplace_fail.cpp ]
+ #[ compile-fail optional_test_inplace_fail2.cpp ]
;
}
diff --git a/test/optional_test_move.cpp b/test/optional_test_move.cpp
new file mode 100644
index 0000000..986ce43
--- /dev/null
+++ b/test/optional_test_move.cpp
@@ -0,0 +1,254 @@
+// Copyright (C) 2014 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/lib/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+//
+// Revisions:
+//
+#include
+#include
+#include
+
+#define BOOST_ENABLE_ASSERT_HANDLER
+
+#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
+#include "boost/mpl/bool.hpp"
+#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
+
+#include "boost/optional/optional.hpp"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "boost/none.hpp"
+
+#include "boost/test/minimal.hpp"
+
+#include "optional_test_common.cpp"
+
+//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
+//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+enum State
+{
+ sDefaultConstructed,
+ sValueCopyConstructed,
+ sValueMoveConstructed,
+ sCopyConstructed,
+ sMoveConstructed,
+ sMoveAssigned,
+ sCopyAssigned,
+ sValueCopyAssigned,
+ sValueMoveAssigned,
+ sMovedFrom,
+ sIntConstructed
+};
+
+struct OracleVal
+{
+ State s;
+ int i;
+ OracleVal(int i = 0) : s(sIntConstructed), i(i) {}
+};
+
+
+struct Oracle
+{
+ State s;
+ OracleVal val;
+
+ Oracle() : s(sDefaultConstructed) {}
+ Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {}
+ Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;}
+ Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {}
+ Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;}
+
+ Oracle& operator=(const OracleVal& v) { s = sValueCopyAssigned; val = v; return *this; }
+ Oracle& operator=(OracleVal&& v) { s = sValueMoveAssigned; val = std::move(v); v.s = sMovedFrom; return *this; }
+ Oracle& operator=(const Oracle& o) { s = sCopyAssigned; val = o.val; return *this; }
+ Oracle& operator=(Oracle&& o) { s = sMoveAssigned; val = std::move(o.val); o.s = sMovedFrom; return *this; }
+};
+
+bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; }
+bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; }
+
+
+void test_move_ctor_from_U()
+{
+ optional o1 ((OracleVal()));
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed);
+
+ OracleVal v1;
+ optional o2 (v1);
+ BOOST_CHECK(o2);
+ std::cout << "AK" << " @@@ " << o2->s << std::endl;
+ BOOST_CHECK(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed );
+ BOOST_CHECK(v1.s == sIntConstructed);
+
+ optional o3 (boost::move(v1));
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed);
+ BOOST_CHECK(v1.s == sMovedFrom);
+}
+
+void test_move_ctor_form_T()
+{
+ optional o1 ((Oracle()));
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sMoveConstructed);
+
+ Oracle v1;
+ optional o2 (v1);
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sCopyConstructed);
+ BOOST_CHECK(v1.s == sDefaultConstructed);
+
+ optional o3 (boost::move(v1));
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sMoveConstructed);
+ BOOST_CHECK(v1.s == sMovedFrom);
+}
+
+void test_move_ctor_from_optional_T()
+{
+ optional o1;
+ optional o2(boost::move(o1));
+
+ BOOST_CHECK(!o1);
+ BOOST_CHECK(!o2);
+
+ optional o3((Oracle()));
+ optional o4(boost::move(o3));
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o4);
+ BOOST_CHECK(o3->s == sMovedFrom);
+ BOOST_CHECK(o4->s == sMoveConstructed);
+
+ optional o5((optional()));
+ BOOST_CHECK(!o5);
+
+ optional o6((optional(Oracle())));
+ BOOST_CHECK(o6);
+ BOOST_CHECK(o6->s == sMoveConstructed);
+
+ optional o7(o6); // does copy ctor from non-const lvalue compile?
+}
+
+void test_move_assign_from_U()
+{
+ optional o1;
+ o1 = OracleVal();
+ BOOST_CHECK(o1);
+
+ BOOST_CHECK(o1->s == sValueMoveConstructed);
+
+ o1 = OracleVal();
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sMoveAssigned);
+
+ OracleVal v1;
+ optional o2;
+ o2 = v1;
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sValueCopyConstructed);
+ BOOST_CHECK(v1.s == sIntConstructed);
+ o2 = v1;
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sCopyAssigned || o2->s == sMoveAssigned);
+ BOOST_CHECK(v1.s == sIntConstructed);
+
+ optional o3;
+ o3 = boost::move(v1);
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sValueMoveConstructed);
+ BOOST_CHECK(v1.s == sMovedFrom);
+}
+
+void test_move_assign_from_T()
+{
+ optional o1;
+ o1 = Oracle();
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sMoveConstructed);
+
+ o1 = Oracle();
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sMoveAssigned);
+
+ Oracle v1;
+ optional o2;
+ o2 = v1;
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sCopyConstructed);
+ BOOST_CHECK(v1.s == sDefaultConstructed);
+ o2 = v1;
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sCopyAssigned);
+ BOOST_CHECK(v1.s == sDefaultConstructed);
+
+ optional o3;
+ o3 = boost::move(v1);
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sMoveConstructed);
+ BOOST_CHECK(v1.s == sMovedFrom);
+}
+
+void test_move_ssign_from_optional_T()
+{
+ optional o1;
+ optional o2;
+ o1 = optional();
+ BOOST_CHECK(!o1);
+ optional o3((Oracle()));
+ o1 = o3;
+ /*BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sDefaultConstructed);
+ BOOST_CHECK(o1);
+ BOOST_CHECK(o1->s == sCopyConstructed);
+
+ o2 = boost::move(o3);
+ BOOST_CHECK(o3);
+ BOOST_CHECK(o3->s == sMovedFrom);
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sMoveConstructed);
+
+ o2 = optional((Oracle()));
+ BOOST_CHECK(o2);
+ BOOST_CHECK(o2->s == sMoveAssigned);*/
+}
+
+
+#endif
+
+int test_main( int, char* [] )
+{
+ try
+ {
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ test_move_ctor_from_U();
+ test_move_ctor_form_T();
+ test_move_ctor_from_optional_T();
+ test_move_assign_from_U();
+ test_move_assign_from_T();
+ test_move_ssign_from_optional_T();
+#endif
+ }
+ catch ( ... )
+ {
+ BOOST_ERROR("Unexpected Exception caught!");
+ }
+
+ return 0;
+}
+
+
From 5c69bac12fd362242838b7c622c4552903808065 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Sat, 26 Apr 2014 00:22:39 +0200
Subject: [PATCH 05/18] Fixed unit tests (still need to add more unit tests for
move semantics)
---
include/boost/optional/optional.hpp | 75 +++++++++++++++++++----------
test/Jamfile.v2 | 24 ++++-----
test/optional_test_move.cpp | 3 +-
3 files changed, 64 insertions(+), 38 deletions(-)
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index c063e94..6933a05 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -27,6 +27,7 @@
#include
#include
#include
+ #include
#include
#include
#include
@@ -425,6 +426,41 @@ class optional_base : public optional_tag
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Constructs in-place using the given factory
+ template
+ void construct ( Expr&& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ;
+ boost_optional_detail::construct(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template
+ void construct ( Expr&& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template
+ void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template
+ void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+#else
// Constructs in-place using the given factory
template
void construct ( Expr const& factory, in_place_factory_base const* )
@@ -459,6 +495,8 @@ class optional_base : public optional_tag
}
#endif
+#endif
+
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
@@ -683,12 +721,16 @@ class optional : public optional_detail::optional_base
// Can throw if the resolved T ctor throws.
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#ifndef BOOST_NO_SFINAE
-#else
+
template
- explicit optional ( Expr&& expr, typename boost::disable_if::type, optional> >::type* = 0 )
+ explicit optional ( Expr&& expr,
+ typename boost::disable_if_c<
+ (boost::is_base_of::type>::value) ||
+ boost::is_same::type, optional>::value ||
+ boost::is_same::type, none_t>::value >::type* = 0
+ )
: base(boost::forward(expr),boost::addressof(expr)) {}
-#endif
+
#else
template
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
@@ -707,11 +749,6 @@ class optional : public optional_detail::optional_base
: base( boost::move(rhs) )
{}
-#ifdef BOOST_NO_SFINAE
- // To avoid too perfect forwarding
- optional ( optional& rhs ) : base( static_cast (rhs) ) {}
-#endif
-
#endif
// No-throw (assuming T::~T() doesn't)
~optional() {}
@@ -722,14 +759,10 @@ class optional : public optional_detail::optional_base
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template
-#if !defined BOOST_NO_SFINAE
- typename boost::disable_if<
- boost::is_same::type, optional>,
+ typename boost::disable_if_c<
+ boost::is_base_of::type>::value || boost::is_same::type, optional>::value || boost::is_same::type, none_t>::value,
optional&
>::type
-#else
- optional&
-#endif
operator= ( Expr&& expr )
{
this->assign_expr(boost::forward(expr),boost::addressof(expr));
@@ -743,8 +776,8 @@ class optional : public optional_detail::optional_base
this->assign_expr(expr,boost::addressof(expr));
return *this ;
}
-#endif
-#endif
+#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
+#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from another convertible optional (converts && deep-copies the rhs value)
// Requires a valid conversion from U to T.
@@ -773,14 +806,6 @@ class optional : public optional_detail::optional_base
this->assign( static_cast (rhs) ) ;
return *this ;
}
-#ifdef BOOST_NO_SFINAE
- // to avoid too perfect forwarding
- optional& operator= ( optional& rhs )
- {
- this->assign( static_cast (rhs) ) ;
- return *this ;
- }
-#endif
#endif
// Assigns from a T (deep-copies the rhs value)
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 62ab883..a146f72 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -17,18 +17,18 @@ import testing ;
{
test-suite optional :
[ run optional_test.cpp ]
- #[ run optional_test_tie.cpp ]
- #[ run optional_test_ref.cpp ]
- #[ run optional_test_inplace.cpp ]
- #[ run optional_test_io.cpp ]
+ [ run optional_test_tie.cpp ]
+ [ run optional_test_ref.cpp ]
+ [ run optional_test_inplace.cpp ]
+ [ run optional_test_io.cpp ]
[ run optional_test_move.cpp ]
- #[ compile-fail optional_test_fail1.cpp ]
- #[ compile-fail optional_test_fail3a.cpp ]
- #[ compile-fail optional_test_fail3b.cpp ]
- #[ compile-fail optional_test_ref_fail1.cpp ]
- #[ compile-fail optional_test_ref_fail3.cpp ]
- #[ compile-fail optional_test_ref_fail4.cpp ]
- #[ compile-fail optional_test_inplace_fail.cpp ]
- #[ compile-fail optional_test_inplace_fail2.cpp ]
+ [ compile-fail optional_test_fail1.cpp ]
+ [ compile-fail optional_test_fail3a.cpp ]
+ [ compile-fail optional_test_fail3b.cpp ]
+ [ compile-fail optional_test_ref_fail1.cpp ]
+ [ compile-fail optional_test_ref_fail3.cpp ]
+ [ compile-fail optional_test_ref_fail4.cpp ]
+ [ compile-fail optional_test_inplace_fail.cpp ]
+ [ compile-fail optional_test_inplace_fail2.cpp ]
;
}
diff --git a/test/optional_test_move.cpp b/test/optional_test_move.cpp
index 986ce43..0f52c2d 100644
--- a/test/optional_test_move.cpp
+++ b/test/optional_test_move.cpp
@@ -146,7 +146,8 @@ void test_move_ctor_from_optional_T()
void test_move_assign_from_U()
{
- optional o1;
+ optional o1 = boost::none; // test if additional ctors didn't break it
+ o1 = boost::none; // test if additional assignments didn't break it
o1 = OracleVal();
BOOST_CHECK(o1);
From c7cf80e5df873e11dab3f6bf01c897c9bb661d7b Mon Sep 17 00:00:00 2001
From: Marcel Raad
Date: Thu, 24 Apr 2014 10:00:43 +0200
Subject: [PATCH 06/18] Use BOOST_EXPLICIT_OPERATOR_BOOL for optional
I often have the problem that when I change a std::wstring to boost::optional and the variable is used as a parameter with Boost.Format, the result silently changes from the string contents to "1".
This change prevents implicit conversion to bool if the compiler supports explicit conversion operators.
---
.../boost_optional/detailed_semantics.html | 9 ++++--
doc/html/boost_optional/synopsis.html | 2 +-
doc/html/index.html | 2 +-
doc/reference.qbk | 8 +++---
include/boost/optional/optional.hpp | 15 ++--------
test/Jamfile.v2 | 1 +
test/optional_test.cpp | 4 +--
...tional_test_fail_implicit_bool_convert.cpp | 28 +++++++++++++++++++
8 files changed, 46 insertions(+), 23 deletions(-)
create mode 100644 test/optional_test_fail_implicit_bool_convert.cpp
diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html
index 4ab1a29..9163af0 100644
--- a/doc/html/boost_optional/detailed_semantics.html
+++ b/doc/html/boost_optional/detailed_semantics.html
@@ -981,16 +981,19 @@
- optional < T >:: operator
unspecified-bool-type () const ;
+ explicit optional < T >:: operator bool () const ;
- Returns: An unspecified value which if
- used on a boolean context is equivalent to (get_ptr () != 0
)
+ Returns: get_ptr () != 0
.
Throws: Nothing.
+
+ Notes: On compilers that do not support
+ explicit conversion operators this falls back to safe-bool idiom.
+
Example:
optional < T > def ;
diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html
index 078dd02..802fa02 100644
--- a/doc/html/boost_optional/synopsis.html
+++ b/doc/html/boost_optional/synopsis.html
@@ -81,7 +81,7 @@
T const * get_ptr () const ;