This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.
CopyConstructible
/MoveConstructible
/CopyAssignable
/MoveAssignable
/Destructible
?Section: 16.4.4.2 [utility.arg.requirements] Status: Open Submitter: Nikolay Ivchenkov Opened: 2012-03-23 Last modified: 2024-12-04
Priority: 3
View all other issues in [utility.arg.requirements].
View all issues with Open status.
Discussion:
According to 16.4.4.2 [utility.arg.requirements] p1
The template definitions in the C++ standard library refer to various named requirements whose details are set out in tables 17-24. In these tables,
T
is an object or reference type to be supplied by a C++ program instantiating a template;a
,b
, andc
are values of type (possiblyconst
)T
;s
andt
are modifiable lvalues of typeT
;u
denotes an identifier;rv
is an rvalue of typeT
; andv
is an lvalue of type (possiblyconst
)T
or an rvalue of typeconst T
.
Is it really intended that T
may be a reference type? If so, what should a
, b
, c
,
s
, t
, u
, rv
, and v
mean? For example, are "int &
" and
"int &&
" MoveConstructible
?
std::swap
and std::for_each
.
Can we use reference types there?
#include <iostream>
#include <utility>
int main()
{
int x = 1;
int y = 2;
std::swap<int &&>(x, y); // undefined?
std::cout << x << " " << y << std::endl;
}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>
struct F
{
void operator()(int n)
{
std::cout << n << std::endl;
++count;
}
int count;
} f;
int main()
{
int arr[] = { 1, 2, 3 };
auto&& result = std::for_each<int *, F &&>( // undefined?
std::begin(arr),
std::end(arr),
std::move(f));
std::cout << "count: " << result.count << std::endl;
}
Are these forms of usage well-defined?
Let's also consider the following constructor ofstd::thread
:
template <class F, class ...Args> explicit thread(F&& f, Args&&... args);Requires:
F
and eachTi
inArgs
shall satisfy theMoveConstructible
requirements.
When the first argument of this constructor is an lvalue (e.g. a name of a global function), template argument for F
is deduced to be lvalue reference type. What should "MoveConstructible
" mean with regard to an lvalue reference
type? Maybe the wording should say that std::decay<F>::type
and each std::decay<Ti>::type
(where
Ti
is an arbitrary item in Args
) shall satisfy the MoveConstructible
requirements?
[2013-03-15 Issues Teleconference]
Moved to Open.
The questions raised by the issue are real, and should have a clear answer.
[2015-10, Kona Saturday afternoon]
STL: std::thread needs to be fixed, and anything behaving like it needs to be fixed, rather than reference types. std::bind gets this right. We need to survey this. GR: That doesn't sound small to me. STL: Seach for CopyConstructible etc. It may be a long change, but not a hard one.
MC: It seems that we don't have a PR. Does anyone have one? Is anyone interested in doing a survey?
[2016-03, Jacksonville]
Casey volunteers to make a survey
[2016-06, Oulu]
During an independent survey performed by Daniel as part of the analysis of LWG 2716(i), some overlap was found between these two issues. Daniel suggested to take responsibility for surveying LWG 2146(i) and opined that the P/R of LWG 2716(i) should restrict to forwarding references, where the deduction to lvalue references can happen without providing an explicit template argument just by providing an lvalue function argument.
[2018-06, Rapperwsil]
Jonathan says that this will be covered by his Omnibus requirements paper.
[2019 Cologne Wednesday night]
Daniel will start working on this again; Marshall to provide rationale why some of the examples are not well-formed.
[2020-10-02; Issue processing telecon: change from P2 to P3]
For the examples given in the original report, the for_each
case is now banned, because 26.2 [algorithms.requirements] p15
forbids explicit template argument lists. std::thread
's constructor
has also been fixed to describe the requirements on decay_t<T>
instead of T
.
We believe we're more careful these days about using remove_cvref
or decay
as needed, but there are still places where we incorrectly
state requirements in terms of types that might be references.
The swap
case still needs solving. Still need a survey.
[2024-03-15; LWG 4047(i) addresses the swap
part]
[2024-12-04; Daniel comments]
The mentioned requirement sets have been renamed a while ago to:
Cpp17CopyConstructible
Cpp17MoveConstructible
Cpp17CopyAssignable
Cpp17MoveAssignable
Cpp17Destructible
Proposed resolution: