does vs2017 need explict move constructor declaration
Clash Royale CLAN TAG#URR8PPP
up vote
10
down vote
favorite
The below code can be compiled successfully using vs2015, but failed using vs2017. vs2017 report "error C2280: “std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)â€Â: attempting to reference a deleted function"
.
#include <unordered_map>
#include <memory>
struct Node
std::unordered_map<int, std::unique_ptr<int>> map_;
//uncomment the following two lines will pass vs2017 compile
//Node(Node&& o) = default;
//Node() = default;
;
int main()
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
It looks like vs2017 need explict move constructor declaration. could anybody explain the reason? thanks.
c++ visual-studio-2017 move-constructor
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |Â
up vote
10
down vote
favorite
The below code can be compiled successfully using vs2015, but failed using vs2017. vs2017 report "error C2280: “std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)â€Â: attempting to reference a deleted function"
.
#include <unordered_map>
#include <memory>
struct Node
std::unordered_map<int, std::unique_ptr<int>> map_;
//uncomment the following two lines will pass vs2017 compile
//Node(Node&& o) = default;
//Node() = default;
;
int main()
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
It looks like vs2017 need explict move constructor declaration. could anybody explain the reason? thanks.
c++ visual-studio-2017 move-constructor
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You're missing#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?
– rubenvb
4 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago
add a comment |Â
up vote
10
down vote
favorite
up vote
10
down vote
favorite
The below code can be compiled successfully using vs2015, but failed using vs2017. vs2017 report "error C2280: “std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)â€Â: attempting to reference a deleted function"
.
#include <unordered_map>
#include <memory>
struct Node
std::unordered_map<int, std::unique_ptr<int>> map_;
//uncomment the following two lines will pass vs2017 compile
//Node(Node&& o) = default;
//Node() = default;
;
int main()
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
It looks like vs2017 need explict move constructor declaration. could anybody explain the reason? thanks.
c++ visual-studio-2017 move-constructor
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
The below code can be compiled successfully using vs2015, but failed using vs2017. vs2017 report "error C2280: “std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)â€Â: attempting to reference a deleted function"
.
#include <unordered_map>
#include <memory>
struct Node
std::unordered_map<int, std::unique_ptr<int>> map_;
//uncomment the following two lines will pass vs2017 compile
//Node(Node&& o) = default;
//Node() = default;
;
int main()
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
It looks like vs2017 need explict move constructor declaration. could anybody explain the reason? thanks.
c++ visual-studio-2017 move-constructor
c++ visual-studio-2017 move-constructor
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 4 hours ago


finn
541
541
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
finn is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
You're missing#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?
– rubenvb
4 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago
add a comment |Â
You're missing#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?
– rubenvb
4 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago
You're missing
#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?– rubenvb
4 hours ago
You're missing
#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?– rubenvb
4 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
4
down vote
When you declare a move constructor, the implicitly declared copy constructor is defined as deleted. On the other hand, when you don't declare a move constructor, the compiler implicitly defines the copy constructor when it need it. And this implicit definition is ill-formed.
unique_ptr
is not CopyInsertable
in a container that uses a standard allocator because it is not copy constructible so the copy constructor of map_
is ill-formed (it could have been declared as deleted, but this is not required by the standard).
As your example code show us, with newer version of MSVC, this ill-formed definition is generated with this example code. I do not think there is something in the standard that forbids it (even if this is realy surprising).
So you should indeed ensure that the copy constructor of Node is declared or implicitly defined as deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor ofstd::unordered_map
(and therefore ofNode
) is notnoexcept
? Then,push_back
, i.e.,emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.
– Daniel Langr
40 mins ago
 |Â
show 3 more comments
up vote
3
down vote
I believe this is a bug, since the same error can be triggered by the following minimal code:
#include <memory>
#include <unordered_map>
#include <vector>
int main()
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
Live demo on GodBolt: https://godbolt.org/z/VApPkH.
Another example:
#include <set>
#include <vector>
struct NonCopyable
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
;
int main()
std::vector<std::set<NonCopyable>> vec;
vec.reserve(1);
add a comment |Â
up vote
2
down vote
Let's look at the std::vector
source code (I replaced pointer
and _Ty
with actual types):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
// move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
// copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
// move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>);
If Node
is no-throw move-constructible or is not copy-constructible, _Uninitialized_move
is called. If Node
is not no-throw move-constructible and is copy-constructible, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible
is std::true_type
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely onstd::is_copy_constructible
in this particular piece of code. I don't have a better answer now.
– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
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
When you declare a move constructor, the implicitly declared copy constructor is defined as deleted. On the other hand, when you don't declare a move constructor, the compiler implicitly defines the copy constructor when it need it. And this implicit definition is ill-formed.
unique_ptr
is not CopyInsertable
in a container that uses a standard allocator because it is not copy constructible so the copy constructor of map_
is ill-formed (it could have been declared as deleted, but this is not required by the standard).
As your example code show us, with newer version of MSVC, this ill-formed definition is generated with this example code. I do not think there is something in the standard that forbids it (even if this is realy surprising).
So you should indeed ensure that the copy constructor of Node is declared or implicitly defined as deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor ofstd::unordered_map
(and therefore ofNode
) is notnoexcept
? Then,push_back
, i.e.,emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.
– Daniel Langr
40 mins ago
 |Â
show 3 more comments
up vote
4
down vote
When you declare a move constructor, the implicitly declared copy constructor is defined as deleted. On the other hand, when you don't declare a move constructor, the compiler implicitly defines the copy constructor when it need it. And this implicit definition is ill-formed.
unique_ptr
is not CopyInsertable
in a container that uses a standard allocator because it is not copy constructible so the copy constructor of map_
is ill-formed (it could have been declared as deleted, but this is not required by the standard).
As your example code show us, with newer version of MSVC, this ill-formed definition is generated with this example code. I do not think there is something in the standard that forbids it (even if this is realy surprising).
So you should indeed ensure that the copy constructor of Node is declared or implicitly defined as deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor ofstd::unordered_map
(and therefore ofNode
) is notnoexcept
? Then,push_back
, i.e.,emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.
– Daniel Langr
40 mins ago
 |Â
show 3 more comments
up vote
4
down vote
up vote
4
down vote
When you declare a move constructor, the implicitly declared copy constructor is defined as deleted. On the other hand, when you don't declare a move constructor, the compiler implicitly defines the copy constructor when it need it. And this implicit definition is ill-formed.
unique_ptr
is not CopyInsertable
in a container that uses a standard allocator because it is not copy constructible so the copy constructor of map_
is ill-formed (it could have been declared as deleted, but this is not required by the standard).
As your example code show us, with newer version of MSVC, this ill-formed definition is generated with this example code. I do not think there is something in the standard that forbids it (even if this is realy surprising).
So you should indeed ensure that the copy constructor of Node is declared or implicitly defined as deleted.
When you declare a move constructor, the implicitly declared copy constructor is defined as deleted. On the other hand, when you don't declare a move constructor, the compiler implicitly defines the copy constructor when it need it. And this implicit definition is ill-formed.
unique_ptr
is not CopyInsertable
in a container that uses a standard allocator because it is not copy constructible so the copy constructor of map_
is ill-formed (it could have been declared as deleted, but this is not required by the standard).
As your example code show us, with newer version of MSVC, this ill-formed definition is generated with this example code. I do not think there is something in the standard that forbids it (even if this is realy surprising).
So you should indeed ensure that the copy constructor of Node is declared or implicitly defined as deleted.
edited 1 hour ago
answered 1 hour ago
Oliv
7,1231750
7,1231750
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor ofstd::unordered_map
(and therefore ofNode
) is notnoexcept
? Then,push_back
, i.e.,emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.
– Daniel Langr
40 mins ago
 |Â
show 3 more comments
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor ofstd::unordered_map
(and therefore ofNode
) is notnoexcept
? Then,push_back
, i.e.,emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.
– Daniel Langr
40 mins ago
1
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune because the generation of the code of the copy constructor is only performed when needed. So the error does not appear within this small example but it may in a larger piece of code.
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
@darune What do you think about that :godbolt.org/z/KG02ua ,
– Oliv
1 hour ago
1
1
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
@darune I think the bug is in the standard requirement. If a standard type is not copy constructible it should be possible to check it with traits. But actually implementing such a requirement would be a real pain. I hope that with concepts this will be fixed.
– Oliv
1 hour ago
1
1
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor of
std::unordered_map
(and therefore of Node
) is not noexcept
? Then, push_back
, i.e., emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.– Daniel Langr
40 mins ago
I don't have VS2017 accessible, but couldn't be the problem with that implicitly-declared move constructor of
std::unordered_map
(and therefore of Node
) is not noexcept
? Then, push_back
, i.e., emplace_back
, may prefer copy constructor (during reallocation) than potentially throwing move constructor (std::move_if_noexcept
)? With user-declared move constructor, the copy constructor is deleted, so throwing move constructor will be used.– Daniel Langr
40 mins ago
 |Â
show 3 more comments
up vote
3
down vote
I believe this is a bug, since the same error can be triggered by the following minimal code:
#include <memory>
#include <unordered_map>
#include <vector>
int main()
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
Live demo on GodBolt: https://godbolt.org/z/VApPkH.
Another example:
#include <set>
#include <vector>
struct NonCopyable
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
;
int main()
std::vector<std::set<NonCopyable>> vec;
vec.reserve(1);
add a comment |Â
up vote
3
down vote
I believe this is a bug, since the same error can be triggered by the following minimal code:
#include <memory>
#include <unordered_map>
#include <vector>
int main()
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
Live demo on GodBolt: https://godbolt.org/z/VApPkH.
Another example:
#include <set>
#include <vector>
struct NonCopyable
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
;
int main()
std::vector<std::set<NonCopyable>> vec;
vec.reserve(1);
add a comment |Â
up vote
3
down vote
up vote
3
down vote
I believe this is a bug, since the same error can be triggered by the following minimal code:
#include <memory>
#include <unordered_map>
#include <vector>
int main()
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
Live demo on GodBolt: https://godbolt.org/z/VApPkH.
Another example:
#include <set>
#include <vector>
struct NonCopyable
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
;
int main()
std::vector<std::set<NonCopyable>> vec;
vec.reserve(1);
I believe this is a bug, since the same error can be triggered by the following minimal code:
#include <memory>
#include <unordered_map>
#include <vector>
int main()
std::vector<std::unordered_map<int, std::unique_ptr<int>>> vec;
vec.reserve(1);
Live demo on GodBolt: https://godbolt.org/z/VApPkH.
Another example:
#include <set>
#include <vector>
struct NonCopyable
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) noexcept = default;
;
int main()
std::vector<std::set<NonCopyable>> vec;
vec.reserve(1);
edited 12 mins ago
answered 20 mins ago
Daniel Langr
5,9742243
5,9742243
add a comment |Â
add a comment |Â
up vote
2
down vote
Let's look at the std::vector
source code (I replaced pointer
and _Ty
with actual types):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
// move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
// copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
// move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>);
If Node
is no-throw move-constructible or is not copy-constructible, _Uninitialized_move
is called. If Node
is not no-throw move-constructible and is copy-constructible, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible
is std::true_type
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely onstd::is_copy_constructible
in this particular piece of code. I don't have a better answer now.
– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
add a comment |Â
up vote
2
down vote
Let's look at the std::vector
source code (I replaced pointer
and _Ty
with actual types):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
// move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
// copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
// move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>);
If Node
is no-throw move-constructible or is not copy-constructible, _Uninitialized_move
is called. If Node
is not no-throw move-constructible and is copy-constructible, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible
is std::true_type
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely onstd::is_copy_constructible
in this particular piece of code. I don't have a better answer now.
– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
add a comment |Â
up vote
2
down vote
up vote
2
down vote
Let's look at the std::vector
source code (I replaced pointer
and _Ty
with actual types):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
// move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
// copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
// move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>);
If Node
is no-throw move-constructible or is not copy-constructible, _Uninitialized_move
is called. If Node
is not no-throw move-constructible and is copy-constructible, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible
is std::true_type
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
Let's look at the std::vector
source code (I replaced pointer
and _Ty
with actual types):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
// move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
// copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
// move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>);
If Node
is no-throw move-constructible or is not copy-constructible, _Uninitialized_move
is called. If Node
is not no-throw move-constructible and is copy-constructible, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible
is std::true_type
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
edited 1 hour ago
answered 1 hour ago


Evg
3,41811334
3,41811334
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely onstd::is_copy_constructible
in this particular piece of code. I don't have a better answer now.
– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
add a comment |Â
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely onstd::is_copy_constructible
in this particular piece of code. I don't have a better answer now.
– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
1
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
1 hour ago
1
1
@darune, the dumb answer is because gcc's and clang's implementations do not rely on
std::is_copy_constructible
in this particular piece of code. I don't have a better answer now.– Evg
1 hour ago
@darune, the dumb answer is because gcc's and clang's implementations do not rely on
std::is_copy_constructible
in this particular piece of code. I don't have a better answer now.– Evg
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
If i understand you correctly that code is in the MSVC vector implementation (?) and isn't that a bug in this case ? It does feel like like a bug, because invoking the move constructor directly does compile fine.
– darune
1 hour ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
38 mins ago
add a comment |Â
finn is a new contributor. Be nice, and check out our Code of Conduct.
finn is a new contributor. Be nice, and check out our Code of Conduct.
finn is a new contributor. Be nice, and check out our Code of Conduct.
finn is a new contributor. Be nice, and check out our Code of Conduct.
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%2f53168836%2fdoes-vs2017-need-explict-move-constructor-declaration%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
You're missing
#include <vector>
but as far as I can tell, that code should compile (and it does on e.g. GCC 8.2). Do you have the latest and greatest VS2017?– rubenvb
4 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
3 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
3 hours ago