Can copy constructors of containers be defined as deleted for non-copyable value types?
Clash Royale CLAN TAG#URR8PPP
up vote
9
down vote
favorite
If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.
using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)
This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.
My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?
c++ containers language-lawyer copy-constructor noncopyable
add a comment |Â
up vote
9
down vote
favorite
If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.
using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)
This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.
My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?
c++ containers language-lawyer copy-constructor noncopyable
add a comment |Â
up vote
9
down vote
favorite
up vote
9
down vote
favorite
If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.
using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)
This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.
My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?
c++ containers language-lawyer copy-constructor noncopyable
If we have a container with non-copyable value type, such a container class still defines the copy constructor, just it may not be invoked.
using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)
This may cause "hidden" problems such as the one discussed here: Does Visual Studio 2017 need an explicit move constructor declaration?.
My question is if Standard library implementations may define such copy constructor as conditionally deleted, namely deleted in case of non-copyable value types. It would make perfect sense to me (at least until there are C++ concepts). Would such implementation be Standard-compliant?
c++ containers language-lawyer copy-constructor noncopyable
c++ containers language-lawyer copy-constructor noncopyable
edited 4 hours ago
asked 4 hours ago
Daniel Langr
6,1192243
6,1192243
add a comment |Â
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
4
down vote
This is not possible ever since vector
got incomplete type support:
struct E
std::vector<E> e;
;
E
is copyable iff std::vector<E>
is copyable, and std::vector<E>
is copyable iff E
is copyable. Turtles all the way down.
Even before that, because the allocator's construct
can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.
add a comment |Â
up vote
3
down vote
For a short answer: no.
If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:
vector(const vector& other);
Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).
The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>
's copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>>
does not satisfy CopyConstructible
requirement, which is very much like having a deleted copy constructor.
As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.
add a comment |Â
up vote
2
down vote
As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[âÂÂNote: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
âÂÂâÂÂend note
âÂÂ]
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
This is not possible ever since vector
got incomplete type support:
struct E
std::vector<E> e;
;
E
is copyable iff std::vector<E>
is copyable, and std::vector<E>
is copyable iff E
is copyable. Turtles all the way down.
Even before that, because the allocator's construct
can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.
add a comment |Â
up vote
4
down vote
This is not possible ever since vector
got incomplete type support:
struct E
std::vector<E> e;
;
E
is copyable iff std::vector<E>
is copyable, and std::vector<E>
is copyable iff E
is copyable. Turtles all the way down.
Even before that, because the allocator's construct
can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.
add a comment |Â
up vote
4
down vote
up vote
4
down vote
This is not possible ever since vector
got incomplete type support:
struct E
std::vector<E> e;
;
E
is copyable iff std::vector<E>
is copyable, and std::vector<E>
is copyable iff E
is copyable. Turtles all the way down.
Even before that, because the allocator's construct
can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.
This is not possible ever since vector
got incomplete type support:
struct E
std::vector<E> e;
;
E
is copyable iff std::vector<E>
is copyable, and std::vector<E>
is copyable iff E
is copyable. Turtles all the way down.
Even before that, because the allocator's construct
can mutilate the constructor arguments as it sees fit, and there's no way for the container to tell if something is "allocator-constructible", conditionally deleting the copy constructor would require some serious design work. The incomplete type support just put the nail in the coffin.
answered 37 mins ago
T.C.
103k13208312
103k13208312
add a comment |Â
add a comment |Â
up vote
3
down vote
For a short answer: no.
If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:
vector(const vector& other);
Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).
The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>
's copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>>
does not satisfy CopyConstructible
requirement, which is very much like having a deleted copy constructor.
As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.
add a comment |Â
up vote
3
down vote
For a short answer: no.
If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:
vector(const vector& other);
Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).
The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>
's copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>>
does not satisfy CopyConstructible
requirement, which is very much like having a deleted copy constructor.
As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
For a short answer: no.
If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:
vector(const vector& other);
Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).
The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>
's copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>>
does not satisfy CopyConstructible
requirement, which is very much like having a deleted copy constructor.
As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.
For a short answer: no.
If we look at the current specification (as of c++17) of std::vector, we have the following signature and description:
vector(const vector& other);
Copy constructor. Constructs the container with the copy of the contents of other. If alloc is not provided, allocator is obtained as if by calling std::allocator_traits::select_on_container_copy_construction(other.get_allocator()).
The copy constructor has the usual canonical signature and the description does not specify any SFINAE condition, so a conforming implementation should not impose stricter requirements such as conditional delete. Nevertheless, an instantiation error will occur if an explicit or implicit call to vector<unique_ptr<T>>
's copy ctor is attempted since the description implies element-wise copy. As such, vector<unique_ptr<T>>
does not satisfy CopyConstructible
requirement, which is very much like having a deleted copy constructor.
As far as I know, there is no syntactic support for a conditional delete but SFINAE conditions and the soon to come Constraints can achieve selective overload resolution. I would still strongly advise against using these on special operations. Special operations should be defined using their usual canonical signature.
answered 53 mins ago
Julien Villemure-Fréchette
515
515
add a comment |Â
add a comment |Â
up vote
2
down vote
As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[âÂÂNote: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
âÂÂâÂÂend note
âÂÂ]
add a comment |Â
up vote
2
down vote
As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[âÂÂNote: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
âÂÂâÂÂend note
âÂÂ]
add a comment |Â
up vote
2
down vote
up vote
2
down vote
As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[âÂÂNote: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
âÂÂâÂÂend note
âÂÂ]
As T.C. says this may not even be feasible but if it was I believe section [member.functions]p2 under Conforming implementations does not allow this:
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[âÂÂNote: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
âÂÂâÂÂend note
âÂÂ]
answered 25 mins ago
Shafik Yaghmour
121k23304503
121k23304503
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53210201%2fcan-copy-constructors-of-containers-be-defined-as-deleted-for-non-copyable-value%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password