std::experimental::function
constructors taking allocator arguments may throw exceptionsSection: 4.2 [fund.ts.v2::func.wrap.func] Status: Resolved Submitter: Tim Song Opened: 2015-12-05 Last modified: 2022-11-22
Priority: 3
View all other issues in [fund.ts.v2::func.wrap.func].
View all issues with Resolved status.
Discussion:
Addresses: fund.ts.v2
[This is essentially LWG 2370, but deals with the fundamentals TS version rather than the one in the standard]
In 4.2 [fund.ts.v2::func.wrap.func] of library fundamentals TS, the constructorstemplate<class A> function(allocator_arg_t, const A&) noexcept; template<class A> function(allocator_arg_t, const A&, nullptr_t) noexcept;
must type-erase and store the provided allocator, since the operator=
specification requires using the "allocator
specified in the construction of" the std::experimental::function
object. This may require a dynamic allocation
and so cannot be noexcept. Similarly, the following constructors
template<class A> function(allocator_arg_t, const A&, const function&); template<class A> function(allocator_arg_t, const A&, function&&); template<class F, class A> function(allocator_arg_t, const A&, F);
cannot satisfy the C++14 requirement that they "shall not throw exceptions if [the function
object to be stored]
is a callable object passed via reference_wrapper
or a function pointer" if they need to type-erase and store the
allocator.
[2016-11-08, Issaquah]
Not adopted during NB comment resolution
[2022-10-12 LWG telecon]
Set status to "Open". This would be resolved by P0987R2.
[2022-11-22 Resolved by P0897R2 accepted in Kona. Status changed: Open → Resolved.]
Proposed resolution:
This wording is relative to N4562.
Edit 4.2 [fund.ts.v2::func.wrap.func], class template function
synopsis, as follows:
namespace std { namespace experimental { inline namespace fundamentals_v2 { […] template<class R, class... ArgTypes> class function<R(ArgTypes...)> { public: […] template<class A> function(allocator_arg_t, const A&)noexcept; template<class A> function(allocator_arg_t, const A&, nullptr_t)noexcept; […] }; […] } // namespace fundamentals_v2 } // namespace experimental […] } // namespace std
Insert the following paragraphs after 4.2.1 [fund.ts.v2::func.wrap.func.con]/1:
[Drafting note: This just reproduces the wording from C++14 with the "shall not throw exceptions for
reference_wrapper
/function pointer" provision deleted. — end drafting note]
-1- When a
function
constructor that takes a first argument of typeallocator_arg_t
is invoked, the second argument is treated as a type-erased allocator (8.3). If the constructor moves or makes a copy of a function object (C++14 §20.9), including an instance of theexperimental::function
class template, then that move or copy is performed by using-allocator construction with allocatorget_memory_resource()
.template <class A> function(allocator_arg_t, const A& a); template <class A> function(allocator_arg_t, const A& a, nullptr_t);-?- Postconditions:
!*this
.template <class A> function(allocator_arg_t, const A& a, const function& f);-?- Postconditions:
-?- Throws: May throw!*this if !f
; otherwise,*this
targets a copy off.target()
.bad_alloc
or any exception thrown by the copy constructor of the stored callable object. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, wheref
's target is an object holding only a pointer or reference to an object and a member function pointer. — end note]template <class A> function(allocator_arg_t, const A& a, function&& f);-?- Effects: If
!f
,*this
has no target; otherwise, move-constructs the target off
into the target of*this
, leavingf
in a valid state with an unspecified value.template <class F, class A> function(allocator_arg_t, const A& a, F f);-?- Requires:
-?- Remarks: This constructor shall not participate in overload resolution unlessF
shall beCopyConstructible
.f
is Callable (C++14 §20.9.11.2) for argument typesArgTypes...
and return typeR
. -?- Postconditions:!*this
if any of the following hold:-?- Otherwise,
f
is a null function pointer value.
f
is a null member pointer value.
F
is an instance of thefunction
class template, and!f
.*this
targets a copy off
initialized withstd::move(f)
. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, wheref
's target is an object holding only a pointer or reference to an object and a member function pointer. — end note] -?- Throws: May throwbad_alloc
or any exception thrown byF
's copy or move constructor.-2- In the following descriptions, let
[…]ALLOCATOR_OF(f)
be the allocator specified in the construction offunction f
, orallocator<char>()
if no allocator was specified.