Created on 2016-09-14.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to N4885.
Edit [func.wrap.func.general], class template function synopsis, as indicated:
namespace std {
template<class> class function; // not defined
template<class R, class... ArgTypes> {
public:
using result_type = R;
// [func.wrap.func.con], construct/copy/destroy
function() noexcept;
function(nullptr_t) noexcept;
function(const function&);
function(function&&) noexcept;
template<class F> function(F&&);
[…]
};
[…]
}
Edit [func.wrap.func.con] as indicated:
template<class F> function(F&& f);Let FD be decay_t<F>.
-8- Constraints:
(8.1) — is_same_v<remove_cvref_t<F>, function> is false, and
(8.2) — FD
Fis Lvalue-Callable ([func.wrap.func.general]) for argument types ArgTypes... and return type R.-?- Mandates:
(?.1) — is_copy_constructible_v<FD> is true, and
(?.2) — is_constructible_v<FD, F> is true.
-9- Preconditions:
-10- Postconditions: !*this is true if any of the following hold:FFD meets the Cpp17CopyConstructible requirements.
(10.1) — f is a null function pointer value.
(10.2) — f is a null member pointer value.
(10.3) —
F is an instanceremove_cvref_t<F> is a specialization of the function class template, and !f is true.-11- Otherwise, *this targets
-12- Throws: Nothing ifa copy of fan object of type FD direct-non-list-initialized withstd::move(f)std::forward<F>(f).fFD is a specialization of reference_wrapper or a function pointer type. Otherwise, may throw bad_alloc or any exception thrown byF's copy or move constructorthe initialization of the target object. -13- Recommended practice: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where fisrefers to an object holding only a pointer or reference to an object and a member function pointer.
[ 2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP. ]
[ 2021-05-20; Reflector poll ]
Set status to Tentatively Ready after five votes in favour during reflector poll.
[ 2021-05-17; Tim comments and revises the wording ]
The additional constraints added in the previous wording can induce constraint recursion, as noted in the discussion of LWG 3493. The wording below changes them to Mandates: instead to allow this issue to make progress independently of that issue.
The proposed resolution below has been implemented and tested on top of libstdc++.[ 2020-11-01; Daniel comments and improves the wording ]
The proposed wording should — following the line of Marshall's "Mandating" papers — extract from the Cpp17CopyConstructible precondition a corresponding Constraints: element and in addition to that the wording should replace old-style elements such as Expects: by the recently agreed on elements.
See also the related issue LWG 3493.Previous resolution [SUPERSEDED]:
This wording is relative to N4868.
Edit [func.wrap.func], class template function synopsis, as indicated:
namespace std { template<class> class function; // not defined template<class R, class... ArgTypes> { public: using result_type = R; // [func.wrap.func.con], construct/copy/destroy function() noexcept; function(nullptr_t) noexcept; function(const function&); function(function&&) noexcept; template<class F> function(F&&); […] }; […] }
Edit [func.wrap.func.con] as indicated:
template<class F> function(F&& f);Let FD be decay_t<F>.
-8- Constraints:
(8.1) — is_same_v<remove_cvref_t<F>, function> is false,
(8.2) — FD
Fis Lvalue-Callable ([func.wrap.func.general]) for argument types ArgTypes... and return type R,(8.3) — is_copy_constructible_v<FD> is true, and
(8.4) — is_constructible_v<FD, F> is true.
-9- Preconditions:
-10- Postconditions: !*this if any of the following hold:FFD meets the Cpp17CopyConstructible requirements.
(10.1) — f is a null function pointer value.
(10.2) — f is a null member pointer value.
(10.3) —
F is an instanceremove_cvref_t<F> is a specialization of the function class template, and !f is true.-11- Otherwise, *this targets
-12- Throws: Nothing ifa copy of fan object of type FD direct-non-list-initialized withstd::move(f)std::forward<F>(f).fFD is a specialization of reference_wrapper or a function pointer type. Otherwise, may throw bad_alloc or any exception thrown byF's copy or move constructorthe initialization of the target object. -13- Recommended practice: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where fisrefers to an object holding only a pointer or reference to an object and a member function pointer.
[ 2019-07-26 Tim provides PR. ]
Previous resolution [SUPERSEDED]:
This wording is relative to N4820.
Edit [func.wrap.func], class template function synopsis, as indicated:
namespace std { template<class> class function; // not defined template<class R, class... ArgTypes> { public: using result_type = R; // [func.wrap.func.con], construct/copy/destroy function() noexcept; function(nullptr_t) noexcept; function(const function&); function(function&&) noexcept; template<class F> function(F&&); […] }; […] }
Edit [func.wrap.func.con] p7-11 as indicated:
template<class F> function(F&& f);
-7- Requires: F shall be Cpp17CopyConstructibleLet FD be decay_t<F>.-8-
Remarks: This constructor template shall not participate in overload resolution unless FConstraints:
(8.1) — is_same_v<FD, function> is false; and
(8.2) — FD is Lvalue-Callable ([func.wrap.func]) for argument types ArgTypes... and return type R.
-?- Expects: FD meets the Cpp17CopyConstructible requirements.
-9- Ensures: !*this if any of the following hold:
(9.1) — f is a null function pointer value.
(9.2) — f is a null member pointer value.
(9.3) —
F is an instanceremove_cvref_t<F> is a specialization of the function class template, and !f is true.-10- Otherwise, *this targets
a copy of fan object of type FD direct-non-list-initialized withstd::move(f)std::forward<F>(f). [Note: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where fisrefers to an object holding only a pointer or reference to an object and a member function pointer. — end note]-11- Throws:
ShallDoes not throw exceptions whenfFD is a function pointer type or a specialization of reference_wrapper<T> for some T. Otherwise, may throw bad_alloc or any exception thrown byF’s copy or move constructorthe initialization of the target object.
I think there's a minor defect in the std::function interface. The constructor template is:
template <class F> function(F f);
while the assignment operator template is
template <class F> function& operator=(F&& f);
The latter came about as a result of LWG 1288, but that one was dealing with a specific issue that wouldn't have affected the constructor. I think the constructor should also take f by forwarding reference, this saves a move in the lvalue/xvalue cases and is also just generally more consistent. Should just make sure that it's stored as std::decay_t<F> instead of F.
Is there any reason to favor a by-value constructor over a forwarding-reference constructor?History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2021-06-07 16:58:04 | admin | set | messages: + msg11881 |
2021-06-07 16:58:04 | admin | set | status: voting -> wp |
2021-05-26 21:11:22 | admin | set | status: ready -> voting |
2021-05-20 08:53:38 | admin | set | messages: + msg11826 |
2021-05-20 08:53:38 | admin | set | status: new -> ready |
2021-05-18 01:56:01 | admin | set | messages: + msg11808 |
2020-11-01 18:00:25 | admin | set | messages: + msg11526 |
2019-07-26 13:42:16 | admin | set | messages: + msg10514 |
2016-10-03 15:43:16 | admin | set | messages: + msg8528 |
2016-09-14 00:00:00 | admin | create |