Issue 2067: packaged_task should have deleted copy c'tor with const parameter (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.
2067. packaged_task should have deleted copy c'tor with const parameter
Section: 32.10.10 [futures.task] Status: C++14 Submitter: Daniel Krügler Opened: 2011-06-16 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [futures.task].
View all issues with C++14 status.
Discussion:
Class template packaged_task is a move-only type with the following form of the deleted copy operations:
packaged_task(packaged_task&) = delete; packaged_task& operator=(packaged_task&) = delete;
Note that the argument types are non-const. This does not look like a typo to me, this form seems to exist from the very first proposing paper on N2276. Using either of form of the copy-constructor did not make much difference before the introduction of defaulted special member functions, but it makes now an observable difference. This was brought to my attention by a question on a German C++ newsgroup where the question was raised why the following code does not compile on a recent gcc:
#include #include #include #include
int main(){ std::packaged_task<void()> someTask([]{ std::cout << std::this_thread::get_id() << std::endl; }); std::thread someThread(std::move(someTask)); // Error here // Remainder omitted }
It turned out that the error was produced by the instantiation of some return type of std::bind which used a defaulted copy-constructor, which leads to a const declaration conflict with [class.copy] p8.
Some aspects of this problem are possibly core-language related, but I consider it more than a service to programmers, if the library would declare the usual form of the copy operations (i.e. those with const first parameter type) as deleted forpackaged_task to prevent such problems.
A similar problem exists for class template basic_ostream in 31.7.6.2 [ostream]:
namespace std { template <class charT, class traits = char_traits > class basic_ostream : virtual public basic_ios<charT,traits> { […]
// 27.7.3.3 Assign/swap basic_ostream& operator=(basic_ostream& rhs) = delete; basic_ostream& operator=(const basic_ostream&& rhs); void swap(basic_ostream& rhs); };
albeit this could be considered as an editorial swap of copy and move assignment operator, I suggest to fix this as part of this issue as well.
[ 2011 Bloomington. ]
Move to Ready.
Proposed resolution:
This wording is relative to the FDIS.
- Modify the class template
basic_ostreamsynopsis in 31.7.6.2 [ostream]as indicated (Note: The prototype signature of the move assignment operator in 31.7.6.2.3 [ostream.assign]is fine):namespace std {
template <class charT, class traits = char_traits >
class basic_ostream : virtual public basic_ios<charT,traits> {
[…]// 27.7.3.3 Assign/swap
basic_ostream& operator=(const basic_ostream& rhs) = delete;
basic_ostream& operator=(constbasic_ostream&& rhs);
void swap(basic_ostream& rhs);
}; - Modify the class template
packaged_tasksynopsis in 32.10.10 [futures.task] p2 as indicated:namespace std {
template class packaged_task; // undefinedtemplate<class R, class... ArgTypes>
class packaged_task<R(ArgTypes...)> {
public:
[…]// no copy
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;[…]
};
[…]
}