You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 89c9f03
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: doc/rvariant.adoc
+25-2Lines changed: 25 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -795,13 +795,13 @@ where `_I_` is the zero-based index of `T` in [.underline]#`{unwrap_recursive_t}
795
795
+
796
796
*_Returns:_* [.underline]#Let `o` denote# a reference to the new contained value. [.underline]#Returns `{unwrap_recursive}(o)`.#
797
797
+
798
-
*_Remarks:_* [.underline]#If `T~_I_~` is a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to construct an intermediate variable `tmp` as if by passing `std::forward<Args>(args)\...` to ``T~_I_~``'s constructor. Then `rvariant` direct-non-list-initializes the contained value of `T~_I_~` with the argument `std::move(tmp)`. (_Note:_ This allows optimization where `rvariant` can be assumed to become never valueless on certain cases.)#
798
+
*_Remarks:_* [.underline]#If `T~_I_~` is a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to construct an intermediate variable `tmp` as if by passing `std::forward<Args>(args)\...` to ``T~_I_~``'s constructor. Then `rvariant` direct-non-list-initializes the contained value of `T~_I_~` with the argument `std::move(tmp)`. Additionally, if `*this` holds a value of a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to destroy that value after constructing such an intermediate variable, for any `T~_I_~`. (_Note:_ This allows optimization where `rvariant` can be assumed to become never valueless on certain cases.)#
799
799
800
800
* [.candidate]#4)# Equivalent to the `std::variant` counterpart, ^https://eel.is/c++draft/variant.mod[[spec\]]^ except:
801
801
+
802
802
*_Returns:_* [.underline]#Let `o` denote# a reference to the new contained value. [.underline]#Returns `{unwrap_recursive}(o)`.#
803
803
+
804
-
*_Remarks:_* [.underline]#If `T~_I_~` is a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to construct an intermediate variable `tmp` as if by passing `il, std::forward<Args>(args)\...` to ``T~_I_~``'s constructor. Then `rvariant` direct-non-list-initializes the contained value of `T~_I_~` with the argument `std::move(tmp)`. (_Note:_ This allows optimization where `rvariant` can be assumed to become never valueless on certain cases.)#
804
+
*_Remarks:_* [.underline]#If `T~_I_~` is a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to construct an intermediate variable `tmp` as if by passing `il, std::forward<Args>(args)\...` to ``T~_I_~``'s constructor. Then `rvariant` direct-non-list-initializes the contained value of `T~_I_~` with the argument `std::move(tmp)`. Additionally, if `*this` holds a value of a specialization of `{recursive_wrapper}` or `{recursive_wrapper_alloca}`, this function is permitted to destroy that value after constructing such an intermediate variable, for any `T~_I_~`. (_Note:_ This allows optimization where `rvariant` can be assumed to become never valueless on certain cases.)#
805
805
806
806
[[rvariant.status]]
807
807
=== Value status [.slug]##<<rvariant.status,[rvariant.status]>>##
@@ -1451,6 +1451,29 @@ _Note 2:_ It is currently unknown whether the recursive instantiation scenario d
1451
1451
*_Effects:_* Equivalent to the `std::indirect` counterpart. ^link:pass:[https://eel.is/c++draft/indirect.ctor#lib:indirect,constructor______][[spec\]]^
1452
1452
1453
1453
1454
+
[[rvariant.recursive.relops]]
1455
+
=== Comparisons
1456
+
Effectively overrides only the ones listed below; rest are the same as `std::indirect` counterparts. ^https://eel.is/c++draft/indirect.relops[[spec\]]^ ^https://eel.is/c++draft/indirect.comp.with.t[[spec\]]^
1457
+
1458
+
[,cpp,subs="+macros,+attributes"]
1459
+
----
1460
+
template<class T, class A, class U, class AA>
1461
+
constexpr bool operator==(recursive_wrapper_alloca<T, A> const& lhs, recursive_wrapper_alloca<U, AA> const& rhs)
1462
+
pass:quotes[[.underline\]#/* no noexcept-specifier */#];pass:quotes[[.candidate\]#// 1#]
1463
+
1464
+
template<class T, class A, class U>
1465
+
constexpr bool operator==(recursive_wrapper_alloca<T, A> const& lhs, U const& rhs)
1466
+
pass:quotes[[.underline\]#/* no noexcept-specifier */#];pass:quotes[[.candidate\]#// 2#]
1467
+
----
1468
+
1469
+
[.candidates]
1470
+
* [.candidate]#1-2)# Equivalent to the `std::indirect` counterparts, except that [.underline]#they have no _noexcept-specifier_#.
1471
+
+
1472
+
*_Note:_* The _noexcept-specifier_ of the `std::indirect` counterparts depends on the comparison of `T`. Since an exception specification is needed whenever the function is selected by overload resolution, such a _noexcept-specifier_ makes the comparison of a recursive type depend on itself; for example, if a class `X` has a defaulted `operator==` and contains `rvariant<..., recursive_wrapper<X>>`, checking the constraints of ``rvariant``'s `operator==` requires the comparison of `X`, which in turn requires checking the same constraints. Some compilers (e.g. GCC) reject such a program. The _noexcept-specifier_ is omitted to break this recursion.
1473
+
1474
+
WARNING: [.underline]#Recursive types must implement their own *non-defaulted* `operatorpass:quotes[<=>]`.# For a class `X` that contains `rvariant<..., recursive_wrapper<X>>`, a defaulted `operatorpass:quotes[<=>]` of `X` requires the result of ``rvariant``'s `operatorpass:quotes[<=>]`, whose constraints and return type in turn require the result of comparing `X` through `recursive_wrapper<X>`. This leads to infinite recursive instantiation, regardless of whether the return type of the defaulted `operatorpass:quotes[<=>]` is `auto` or a specific comparison category type. This is a limitation of the language itself; standard containers have a similar limitation (e.g. a class `X` that contains `std::vector<X>` cannot have a defaulted `operatorpass:quotes[<=>]` whose return type is `auto`).
<p><strong><em>Returns:</em></strong><spanclass="underline">Let <code>o</code> denote</span> a reference to the new contained value. <spanclass="underline">Returns <code><ahref="#rvariant.recursive.helper">unwrap_recursive</a>(o)</code>.</span></p>
1940
1941
</div>
1941
1942
<divclass="paragraph">
1942
-
<p><strong><em>Remarks:</em></strong><spanclass="underline">If <code>T<sub><em>I</em></sub></code> is a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to construct an intermediate variable <code>tmp</code> as if by passing <code>std::forward<Args>(args)...</code> to <code>T<sub><em>I</em></sub></code>'s constructor. Then <code>rvariant</code> direct-non-list-initializes the contained value of <code>T<sub><em>I</em></sub></code> with the argument <code>std::move(tmp)</code>. (<em>Note:</em> This allows optimization where <code>rvariant</code> can be assumed to become never valueless on certain cases.)</span></p>
1943
+
<p><strong><em>Remarks:</em></strong><spanclass="underline">If <code>T<sub><em>I</em></sub></code> is a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to construct an intermediate variable <code>tmp</code> as if by passing <code>std::forward<Args>(args)...</code> to <code>T<sub><em>I</em></sub></code>'s constructor. Then <code>rvariant</code> direct-non-list-initializes the contained value of <code>T<sub><em>I</em></sub></code> with the argument <code>std::move(tmp)</code>. Additionally, if <code>*this</code> holds a value of a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to destroy that value after constructing such an intermediate variable, for any <code>T<sub><em>I</em></sub></code>. (<em>Note:</em> This allows optimization where <code>rvariant</code> can be assumed to become never valueless on certain cases.)</span></p>
<p><strong><em>Returns:</em></strong><spanclass="underline">Let <code>o</code> denote</span> a reference to the new contained value. <spanclass="underline">Returns <code><ahref="#rvariant.recursive.helper">unwrap_recursive</a>(o)</code>.</span></p>
1949
1950
</div>
1950
1951
<divclass="paragraph">
1951
-
<p><strong><em>Remarks:</em></strong><spanclass="underline">If <code>T<sub><em>I</em></sub></code> is a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to construct an intermediate variable <code>tmp</code> as if by passing <code>il, std::forward<Args>(args)...</code> to <code>T<sub><em>I</em></sub></code>'s constructor. Then <code>rvariant</code> direct-non-list-initializes the contained value of <code>T<sub><em>I</em></sub></code> with the argument <code>std::move(tmp)</code>. (<em>Note:</em> This allows optimization where <code>rvariant</code> can be assumed to become never valueless on certain cases.)</span></p>
1952
+
<p><strong><em>Remarks:</em></strong><spanclass="underline">If <code>T<sub><em>I</em></sub></code> is a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to construct an intermediate variable <code>tmp</code> as if by passing <code>il, std::forward<Args>(args)...</code> to <code>T<sub><em>I</em></sub></code>'s constructor. Then <code>rvariant</code> direct-non-list-initializes the contained value of <code>T<sub><em>I</em></sub></code> with the argument <code>std::move(tmp)</code>. Additionally, if <code>*this</code> holds a value of a specialization of <code><ahref="#rvariant.recursive">recursive_wrapper</a></code> or <code><ahref="#rvariant.recursive">recursive_wrapper_alloca</a></code>, this function is permitted to destroy that value after constructing such an intermediate variable, for any <code>T<sub><em>I</em></sub></code>. (<em>Note:</em> This allows optimization where <code>rvariant</code> can be assumed to become never valueless on certain cases.)</span></p>
<p>Effectively overrides only the ones listed below; rest are the same as <code>std::indirect</code> counterparts. <sup><ahref="https://eel.is/cdraft/indirect.relops[[spec\]]^ ^https://eel.is/cdraft/indirect.comp.with.t">[spec]</a></sup></p>
2828
+
</div>
2829
+
<divclass="listingblock">
2830
+
<divclass="content">
2831
+
<preclass="highlightjs highlight"><codeclass="language-cpp hljs" data-lang="cpp">template<class T, class A, class U, class AA>
<spanclass="underline">/* no noexcept-specifier */</span>;<spanclass="candidate">// 1</span>
2834
+
2835
+
template<class T, class A, class U>
2836
+
constexpr bool operator==(recursive_wrapper_alloca<T, A> const& lhs, U const& rhs)
2837
+
<spanclass="underline">/* no noexcept-specifier */</span>;<spanclass="candidate">// 2</span></code></pre>
2838
+
</div>
2839
+
</div>
2840
+
<divclass="ulist candidates">
2841
+
<ul>
2842
+
<li>
2843
+
<p><spanclass="candidate">1-2)</span> Equivalent to the <code>std::indirect</code> counterparts, except that <spanclass="underline">they have no <em>noexcept-specifier</em></span>.</p>
2844
+
<divclass="paragraph">
2845
+
<p><strong><em>Note:</em></strong> The <em>noexcept-specifier</em> of the <code>std::indirect</code> counterparts depends on the comparison of <code>T</code>. Since an exception specification is needed whenever the function is selected by overload resolution, such a <em>noexcept-specifier</em> makes the comparison of a recursive type depend on itself; for example, if a class <code>X</code> has a defaulted <code>operator==</code> and contains <code>rvariant<…​, recursive_wrapper<X>></code>, checking the constraints of <code>rvariant</code>'s <code>operator==</code> requires the comparison of <code>X</code>, which in turn requires checking the same constraints. Some compilers (e.g. GCC) reject such a program. The <em>noexcept-specifier</em> is omitted to break this recursion.</p>
2846
+
</div>
2847
+
</li>
2848
+
</ul>
2849
+
</div>
2850
+
<divclass="admonitionblock warning">
2851
+
<table>
2852
+
<tr>
2853
+
<tdclass="icon">
2854
+
<iclass="fa icon-warning" title="Warning"></i>
2855
+
</td>
2856
+
<tdclass="content">
2857
+
<spanclass="underline">Recursive types must implement their own <strong>non-defaulted</strong><code>operator<=></code>.</span> For a class <code>X</code> that contains <code>rvariant<…​, recursive_wrapper<X>></code>, a defaulted <code>operator<=></code> of <code>X</code> requires the result of <code>rvariant</code>'s <code>operator<=></code>, whose constraints and return type in turn require the result of comparing <code>X</code> through <code>recursive_wrapper<X></code>. This leads to infinite recursive instantiation, regardless of whether the return type of the defaulted <code>operator<=></code> is <code>auto</code> or a specific comparison category type. This is a limitation of the language itself; standard containers have a similar limitation (e.g. a class <code>X</code> that contains <code>std::vector<X></code> cannot have a defaulted <code>operator<=></code> whose return type is <code>auto</code>).
0 commit comments