@@ -159,7 +159,7 @@ namespace STDEXEC::__any
159159 struct __any_ptr ;
160160
161161 template <template <class > class _Interface >
162- struct __any_const_ptr ;
162+ struct __any_cptr ;
163163
164164 template <template <class > class ... _BaseInterfaces>
165165 struct __extends ;
@@ -265,7 +265,7 @@ namespace STDEXEC::__any
265265 [[nodiscard]]
266266 constexpr auto operator ()(_Interface<_Base> const &__arg) const noexcept
267267 {
268- return __any_const_ptr <_Interface>(std::addressof (__arg));
268+ return __any_cptr <_Interface>(std::addressof (__arg));
269269 }
270270 };
271271
@@ -308,15 +308,39 @@ namespace STDEXEC::__any
308308 STDEXEC::__any::__interface_cast<_BaseInterface>(__arg);
309309 };
310310
311+ // ////////////////////////////////////////////////////////////////////////////////////////
312+ enum class __box_kind
313+ {
314+ __abstract,
315+ __object,
316+ __proxy
317+ };
318+
319+ // ////////////////////////////////////////////////////////////////////////////////////////
320+ enum class __root_kind
321+ {
322+ __value,
323+ __reference
324+ };
325+
311326 // ////////////////////////////////////////////////////////////////////////////////////////
312327 // __is_small: Model is Interface<_Ty> for some concrete _Ty
313328 template <class _Model >
314329 [[nodiscard]]
315330 constexpr bool __is_small (size_t __buffer_size) noexcept
316331 {
317- constexpr bool __nothrow_movable = !__extension_of<_Model, __imovable>
318- || std::is_nothrow_move_constructible_v<_Model>;
319- return sizeof (_Model) <= __buffer_size && __nothrow_movable;
332+ if constexpr (_Model::__root_kind == __root_kind::__reference)
333+ {
334+ STDEXEC_ASSERT (sizeof (_Model) <= __buffer_size);
335+ return true ;
336+ }
337+ else
338+ {
339+ // If _Model requires movability, then it must be nothrow moveable to be small.
340+ STDEXEC_CONSTEXPR_LOCAL bool __nothrow_movable = !__extension_of<_Model, __imovable>
341+ || __nothrow_move_constructible<_Model>;
342+ return sizeof (_Model) <= __buffer_size && __nothrow_movable;
343+ }
320344 }
321345
322346 // ////////////////////////////////////////////////////////////////////////////////////////
@@ -372,19 +396,6 @@ namespace STDEXEC::__any
372396 template <template <class > class _Interface , class _BaseInterfaces = __bases_of<_Interface>>
373397 using __iabstract = _Interface<__mcall1<_BaseInterfaces, __iroot>>;
374398
375- enum class __box_kind
376- {
377- __abstract,
378- __object,
379- __proxy
380- };
381-
382- enum class __root_kind
383- {
384- __value,
385- __reference
386- };
387-
388399 // ////////////////////////////////////////////////////////////////////////////////////////
389400 // __iroot
390401 struct __iroot
@@ -454,6 +465,14 @@ namespace STDEXEC::__any
454465 : __val_(static_cast <_Args &&>(__args)...)
455466 {}
456467
468+ template <class _Fn , class ... _Args>
469+ constexpr explicit __box (__in_place_from_t , _Fn &&__fn, _Args &&...__args)
470+ noexcept (__nothrow_callable<_Fn, _Args...>)
471+ : __val_(static_cast <_Fn &&>(__fn)(static_cast <_Args &&>(__args)...))
472+ {
473+ static_assert (__same_as<__call_result_t <_Fn, _Args...>, _Value>);
474+ }
475+
457476 template <class _Self >
458477 [[nodiscard]]
459478 static constexpr auto __value_ (_Self &&__self) noexcept -> auto &&
@@ -1140,10 +1159,9 @@ namespace STDEXEC::__any
11401159
11411160 STDEXEC_IF_NOT_CONSTEVAL
11421161 {
1143- STDEXEC_ASSERT ((std::is_convertible_v <_Value &, __value_ref_t >)
1162+ STDEXEC_ASSERT ((__std::convertible_to <_Value &, __value_ref_t >)
11441163 && " attempt to get a mutable reference from a const reference, or an rvalue "
1145- " from an "
1146- " lvalue" );
1164+ " from an lvalue" );
11471165 }
11481166
11491167 if (__self.__is_indirect_ ())
@@ -1232,6 +1250,11 @@ namespace STDEXEC::__any
12321250 }
12331251 }
12341252
1253+ // __reference_proxy_root is not movable or copyable to preserve const-correctness of
1254+ // __any_cptr. Dereferencing an __any_cptr returns an lvalue reference to a const
1255+ // __reference_proxy_model. If __reference_proxy_model were copyable or movable, then
1256+ // it would be possible to cast away const-ness simply by copying or moving the
1257+ // __reference_proxy_model into a non-const object. That would be bad.
12351258 __reference_proxy_root (__reference_proxy_root &&) = delete ;
12361259 __reference_proxy_root &operator =(__reference_proxy_root &&) = delete ;
12371260
@@ -1249,10 +1272,7 @@ namespace STDEXEC::__any
12491272
12501273 constexpr ~__reference_proxy_root ()
12511274 {
1252- STDEXEC_IF_CONSTEVAL
1253- {
1254- __reset_ ();
1255- }
1275+ __reset_ ();
12561276 }
12571277
12581278 constexpr void swap (__reference_proxy_root &__other) noexcept
@@ -1287,8 +1307,7 @@ namespace STDEXEC::__any
12871307 // ! introducing an indirection.
12881308 // ! @post __is_tagged() == true
12891309 auto &__ptr = *__std::start_lifetime_as<__tagged_ptr>(__buff_);
1290- __ptr = static_cast <__iabstract<_Interface> *>(
1291- std::addressof (STDEXEC::__unconst (__model)));
1310+ __ptr = static_cast <__interface_type *>(std::addressof (STDEXEC::__unconst (__model)));
12921311 }
12931312 else
12941313 {
@@ -1592,7 +1611,7 @@ namespace STDEXEC::__any
15921611
15931612 template <template <class > class _Interface >
15941613 [[nodiscard]]
1595- constexpr auto *operator ()(__any_const_ptr <_Interface> const &__ptr) const
1614+ constexpr auto *operator ()(__any_cptr <_Interface> const &__ptr) const
15961615 {
15971616 return (*this )(__ptr.operator ->());
15981617 }
@@ -1684,6 +1703,16 @@ namespace STDEXEC::__any
16841703 (*this ).template __emplace_ <_Value>(static_cast <_Args &&>(__args)...);
16851704 }
16861705
1706+ template <class _Fn , class ... _Args>
1707+ constexpr explicit __any (__in_place_from_t , _Fn &&__fn, _Args &&...__args)
1708+ : __any()
1709+ {
1710+ using __value_t = __decay_t <__call_result_t <_Fn, _Args...>>;
1711+ (*this ).template __emplace_ <__value_t >(
1712+ __emplace_from{[&]() noexcept (__nothrow_callable<_Fn, _Args...>)
1713+ { return static_cast <_Fn &&>(__fn)(static_cast <_Args &&>(__args)...); }});
1714+ }
1715+
16871716 // Implicit derived-to-base conversion constructor
16881717 template <class _Other >
16891718 requires __extension_of<_Interface<_Other>, __imovable>
@@ -1797,7 +1826,7 @@ namespace STDEXEC::__any
17971826 constexpr __any_ptr_base (__any_ptr_base const &__other) noexcept
17981827 : __reference_()
17991828 {
1800- (* this ). __proxy_assign ( std::addressof ( __other.__reference_ ) );
1829+ __reference_. __copy ( __other.__reference_ );
18011830 }
18021831
18031832 template <template <class > class _OtherInterface >
@@ -1811,7 +1840,7 @@ namespace STDEXEC::__any
18111840 constexpr __any_ptr_base &operator =(__any_ptr_base const &__other) noexcept
18121841 {
18131842 __reset (__reference_);
1814- (* this ). __proxy_assign ( std::addressof ( __other.__reference_ ) );
1843+ __reference_. __copy ( __other.__reference_ );
18151844 return *this ;
18161845 }
18171846
@@ -1847,9 +1876,8 @@ namespace STDEXEC::__any
18471876
18481877 template <template <class > class >
18491878 friend struct __any_ptr_base ;
1850-
18511879 friend struct __any_ptr <_Interface>;
1852- friend struct __any_const_ptr <_Interface>;
1880+ friend struct __any_cptr <_Interface>;
18531881
18541882 // ! @param __other A pointer to a value proxy model implementing _Interface.
18551883 template <__extension_of<_Interface> _CvValueProxy>
@@ -1917,9 +1945,9 @@ namespace STDEXEC::__any
19171945
19181946 // Disable const-to-mutable conversions:
19191947 template <template <class > class _Other >
1920- __any_ptr (__any_const_ptr <_Other> const &) = delete ;
1948+ __any_ptr (__any_cptr <_Other> const &) = delete ;
19211949 template <template <class > class _Other >
1922- __any_ptr &operator =(__any_const_ptr <_Other> const &) = delete ;
1950+ __any_ptr &operator =(__any_cptr <_Other> const &) = delete ;
19231951
19241952 template <__model_of<_Interface> _Value>
19251953 constexpr __any_ptr (_Value *__value_ptr) noexcept
@@ -1974,9 +2002,9 @@ namespace STDEXEC::__any
19742002 STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __any_ptr (_Interface<_Base> *) -> __any_ptr<_Interface>;
19752003
19762004 // ////////////////////////////////////////////////////////////////////////////////////////
1977- // __any_const_ptr
2005+ // __any_cptr
19782006 template <template <class > class _Interface >
1979- struct __any_const_ptr : __any_ptr_base<_Interface>
2007+ struct __any_cptr : __any_ptr_base<_Interface>
19802008 {
19812009 using __reference = __any_ptr_base<_Interface>::__model_type const ;
19822010 using __pointer = __reference *;
@@ -1985,36 +2013,36 @@ namespace STDEXEC::__any
19852013 using __any_ptr_base<_Interface>::operator =;
19862014
19872015 template <__model_of<_Interface> _Value>
1988- constexpr __any_const_ptr (_Value const *__value_ptr) noexcept
2016+ constexpr __any_cptr (_Value const *__value_ptr) noexcept
19892017 : __any_ptr_base<_Interface>()
19902018 {
19912019 (*this ).__value_assign (__value_ptr);
19922020 }
19932021
19942022 template <__extension_of<_Interface> _Proxy>
1995- constexpr __any_const_ptr (_Proxy const *__proxy_ptr) noexcept
2023+ constexpr __any_cptr (_Proxy const *__proxy_ptr) noexcept
19962024 : __any_ptr_base<_Interface>()
19972025 {
19982026 (*this ).__proxy_assign (__proxy_ptr);
19992027 }
20002028
20012029 template <__model_of<_Interface> _Value>
2002- constexpr __any_const_ptr &operator =(_Value const *__value_ptr) noexcept
2030+ constexpr __any_cptr &operator =(_Value const *__value_ptr) noexcept
20032031 {
20042032 __reset ((*this ).__reference_ );
20052033 (*this ).__value_assign (__value_ptr);
20062034 return *this ;
20072035 }
20082036
20092037 template <__extension_of<_Interface> _Proxy>
2010- constexpr __any_const_ptr &operator =(_Proxy const *__proxy_ptr) noexcept
2038+ constexpr __any_cptr &operator =(_Proxy const *__proxy_ptr) noexcept
20112039 {
20122040 __reset ((*this ).__reference_ );
20132041 (*this ).__proxy_assign (__proxy_ptr);
20142042 return *this ;
20152043 }
20162044
2017- friend constexpr void swap (__any_const_ptr &__lhs, __any_const_ptr &__rhs) noexcept
2045+ friend constexpr void swap (__any_cptr &__lhs, __any_cptr &__rhs) noexcept
20182046 {
20192047 __lhs.__reference_ .swap (__rhs.__reference_ );
20202048 }
@@ -2034,7 +2062,7 @@ namespace STDEXEC::__any
20342062
20352063 template <template <class > class _Interface , class _Base >
20362064 STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
2037- __any_const_ptr (_Interface<_Base> const *) -> __any_const_ptr <_Interface>;
2065+ __any_cptr (_Interface<_Base> const *) -> __any_cptr <_Interface>;
20382066
20392067 // ////////////////////////////////////////////////////////////////////////////////////////
20402068 // __iequality_comparable
@@ -2053,7 +2081,7 @@ namespace STDEXEC::__any
20532081 private:
20542082 [[nodiscard]]
20552083 // NOLINTNEXTLINE(modernize-use-override)
2056- constexpr virtual bool __equal_to (__any_const_ptr <__iequality_comparable> __other) const
2084+ constexpr virtual bool __equal_to (__any_cptr <__iequality_comparable> __other) const
20572085 {
20582086 auto const &type = STDEXEC::__any::__type (*this );
20592087
0 commit comments