does vs2017 need explicit move constructor declaration
Clash Royale CLAN TAG#URR8PPP
up vote
11
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 explicit 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
11
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 explicit 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
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 hours ago
add a comment |Â
up vote
11
down vote
favorite
up vote
11
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 explicit 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 explicit 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.
edited 12 mins ago


Mike Kinghan
28.7k762106
28.7k762106
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 5 hours ago


finn
592
592
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
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 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
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 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
5 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
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 hours ago
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
6
down vote
Minimal example:
#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:
std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280
UPDATE
I believe the compilation error is legal. Vector's reallocation function can transfer (contents of) elements by using std::move_if_noexcept
, therefore preferring copy constructors to throwing move constructors.
In libstdc++ (GCC) / libc++ (clang), move constructor of std::unordered_map
is (seemingly) noexcept
. Consequently, copy constructor is not at all involved.
On the other hand, implemnetation from MSVC 2017 seemingly does not specify move constructor of std::unordered_map
as noexcept
. Therefore, vector's reallocation function via std::move_if_noexcept
tries to invoke copy constructor. This violates the requirements for containers in general, since value type (std::pair<const int, std::unique_ptr<int>>
in this case) is not copy-insertable (see, e.g., here http://eel.is/c++draft/container.requirements.general#tab:containers.container.requirements).
Finally, if you user-define move constructor, the implicitly declared copy constructor is defined as deleted. And, deleted implicitly declared copy constructor does not participate in overload resolution.
Is this realy a bug?std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.
– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor ofstd::unordered_map
is notnoexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it isnoexcept
.
– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
add a comment |Â
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
2 hours 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
2 hours 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
1 hour ago
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible withunordered_map
, and ended up having to use private inheritance fromstd::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
whereAllowCopy
is empty andDisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.
– Arne Vogel
1 hour ago
2
is_nothrow_move_constructible_v<Node>
isfalse
in MSVC, so it tries to copy and fails; it istrue
in gcc, so it moves. Ifis_nothrow_move_constructible_v<Node>
is forced to becomefalse
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree onis_nothrow_move_constructible_v<Node>
value?
– Evg
33 mins ago
 |Â
show 5 more comments
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, otherwise, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible_v
is true
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
libstdc++ implements std::vector
in a similar way, but there std::is_nothrow_move_constructible_v<Node>
is true
in contrast to MSVC, where it is false
. So, move semantics is used and the compiler does not try to generate the copy-constructor.
But if we force is_nothrow_move_constructible_v
to become false
struct Base
Base() = default;
Base(const S&) = default;
Base(Base&&) noexcept(false)
;
struct Node : Base
std::unordered_map<int, std::unique_ptr<int>> map;
;
int main()
std::vector<Node> vec;
vec.reserve(1);
the same error occurs:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 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
6
down vote
Minimal example:
#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:
std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280
UPDATE
I believe the compilation error is legal. Vector's reallocation function can transfer (contents of) elements by using std::move_if_noexcept
, therefore preferring copy constructors to throwing move constructors.
In libstdc++ (GCC) / libc++ (clang), move constructor of std::unordered_map
is (seemingly) noexcept
. Consequently, copy constructor is not at all involved.
On the other hand, implemnetation from MSVC 2017 seemingly does not specify move constructor of std::unordered_map
as noexcept
. Therefore, vector's reallocation function via std::move_if_noexcept
tries to invoke copy constructor. This violates the requirements for containers in general, since value type (std::pair<const int, std::unique_ptr<int>>
in this case) is not copy-insertable (see, e.g., here http://eel.is/c++draft/container.requirements.general#tab:containers.container.requirements).
Finally, if you user-define move constructor, the implicitly declared copy constructor is defined as deleted. And, deleted implicitly declared copy constructor does not participate in overload resolution.
Is this realy a bug?std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.
– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor ofstd::unordered_map
is notnoexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it isnoexcept
.
– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
add a comment |Â
up vote
6
down vote
Minimal example:
#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:
std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280
UPDATE
I believe the compilation error is legal. Vector's reallocation function can transfer (contents of) elements by using std::move_if_noexcept
, therefore preferring copy constructors to throwing move constructors.
In libstdc++ (GCC) / libc++ (clang), move constructor of std::unordered_map
is (seemingly) noexcept
. Consequently, copy constructor is not at all involved.
On the other hand, implemnetation from MSVC 2017 seemingly does not specify move constructor of std::unordered_map
as noexcept
. Therefore, vector's reallocation function via std::move_if_noexcept
tries to invoke copy constructor. This violates the requirements for containers in general, since value type (std::pair<const int, std::unique_ptr<int>>
in this case) is not copy-insertable (see, e.g., here http://eel.is/c++draft/container.requirements.general#tab:containers.container.requirements).
Finally, if you user-define move constructor, the implicitly declared copy constructor is defined as deleted. And, deleted implicitly declared copy constructor does not participate in overload resolution.
Is this realy a bug?std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.
– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor ofstd::unordered_map
is notnoexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it isnoexcept
.
– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Minimal example:
#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:
std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280
UPDATE
I believe the compilation error is legal. Vector's reallocation function can transfer (contents of) elements by using std::move_if_noexcept
, therefore preferring copy constructors to throwing move constructors.
In libstdc++ (GCC) / libc++ (clang), move constructor of std::unordered_map
is (seemingly) noexcept
. Consequently, copy constructor is not at all involved.
On the other hand, implemnetation from MSVC 2017 seemingly does not specify move constructor of std::unordered_map
as noexcept
. Therefore, vector's reallocation function via std::move_if_noexcept
tries to invoke copy constructor. This violates the requirements for containers in general, since value type (std::pair<const int, std::unique_ptr<int>>
in this case) is not copy-insertable (see, e.g., here http://eel.is/c++draft/container.requirements.general#tab:containers.container.requirements).
Finally, if you user-define move constructor, the implicitly declared copy constructor is defined as deleted. And, deleted implicitly declared copy constructor does not participate in overload resolution.
Minimal example:
#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:
std::unordered_map<int, std::unique_ptr<int>> m;
auto m2 = std::move(m); // ok
auto m3 = std::move_if_noexcept(m); // error C2280
UPDATE
I believe the compilation error is legal. Vector's reallocation function can transfer (contents of) elements by using std::move_if_noexcept
, therefore preferring copy constructors to throwing move constructors.
In libstdc++ (GCC) / libc++ (clang), move constructor of std::unordered_map
is (seemingly) noexcept
. Consequently, copy constructor is not at all involved.
On the other hand, implemnetation from MSVC 2017 seemingly does not specify move constructor of std::unordered_map
as noexcept
. Therefore, vector's reallocation function via std::move_if_noexcept
tries to invoke copy constructor. This violates the requirements for containers in general, since value type (std::pair<const int, std::unique_ptr<int>>
in this case) is not copy-insertable (see, e.g., here http://eel.is/c++draft/container.requirements.general#tab:containers.container.requirements).
Finally, if you user-define move constructor, the implicitly declared copy constructor is defined as deleted. And, deleted implicitly declared copy constructor does not participate in overload resolution.
edited 2 mins ago
answered 1 hour ago
Daniel Langr
6,0042243
6,0042243
Is this realy a bug?std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.
– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor ofstd::unordered_map
is notnoexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it isnoexcept
.
– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
add a comment |Â
Is this realy a bug?std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.
– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor ofstd::unordered_map
is notnoexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it isnoexcept
.
– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
Is this realy a bug?
std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.– Oliv
41 mins ago
Is this realy a bug?
std::is_copy_constructible_v<std::unordered_map<int, std::unique_ptr<int>>>
is true even if any attempt to copy such a type will result in a compilation error. Moreover it will also be detected as CopyInsertable, even if any try to instantiate the code to copy insert it will result in a compilation error.– Oliv
41 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor of
std::unordered_map
is not noexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it is noexcept
.– Daniel Langr
24 mins ago
@Oliv That's a good question. It seems that the problem is that the move constructor of
std::unordered_map
is not noexcept
in MSVC 2017 (which is seemingly not required by the Standard, or is it?). In libstdc++/libc++, it is noexcept
.– Daniel Langr
24 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
@Oliv I updated my answer, I guess you are right. I even don't think now that it is "surprising".
– Daniel Langr
15 mins ago
add a comment |Â
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
2 hours 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
2 hours 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
1 hour ago
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible withunordered_map
, and ended up having to use private inheritance fromstd::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
whereAllowCopy
is empty andDisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.
– Arne Vogel
1 hour ago
2
is_nothrow_move_constructible_v<Node>
isfalse
in MSVC, so it tries to copy and fails; it istrue
in gcc, so it moves. Ifis_nothrow_move_constructible_v<Node>
is forced to becomefalse
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree onis_nothrow_move_constructible_v<Node>
value?
– Evg
33 mins ago
 |Â
show 5 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
2 hours 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
2 hours 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
1 hour ago
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible withunordered_map
, and ended up having to use private inheritance fromstd::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
whereAllowCopy
is empty andDisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.
– Arne Vogel
1 hour ago
2
is_nothrow_move_constructible_v<Node>
isfalse
in MSVC, so it tries to copy and fails; it istrue
in gcc, so it moves. Ifis_nothrow_move_constructible_v<Node>
is forced to becomefalse
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree onis_nothrow_move_constructible_v<Node>
value?
– Evg
33 mins ago
 |Â
show 5 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 2 hours ago
answered 2 hours ago
Oliv
7,1281750
7,1281750
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
1 hour ago
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible withunordered_map
, and ended up having to use private inheritance fromstd::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
whereAllowCopy
is empty andDisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.
– Arne Vogel
1 hour ago
2
is_nothrow_move_constructible_v<Node>
isfalse
in MSVC, so it tries to copy and fails; it istrue
in gcc, so it moves. Ifis_nothrow_move_constructible_v<Node>
is forced to becomefalse
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree onis_nothrow_move_constructible_v<Node>
value?
– Evg
33 mins ago
 |Â
show 5 more comments
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
1 hour ago
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible withunordered_map
, and ended up having to use private inheritance fromstd::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
whereAllowCopy
is empty andDisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.
– Arne Vogel
1 hour ago
2
is_nothrow_move_constructible_v<Node>
isfalse
in MSVC, so it tries to copy and fails; it istrue
in gcc, so it moves. Ifis_nothrow_move_constructible_v<Node>
is forced to becomefalse
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree onis_nothrow_move_constructible_v<Node>
value?
– Evg
33 mins ago
1
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours ago
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours 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
1 hour 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
1 hour ago
3
3
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible with
unordered_map
, and ended up having to use private inheritance from std::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
where AllowCopy
is empty and DisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.– Arne Vogel
1 hour ago
The type traits magic to do this "correctly" is surprisingly complex. I implemented an open addressing hash map (and set) that is mostly API-compatible with
unordered_map
, and ended up having to use private inheritance from std::conditional<std::is_copy_constructible<...>::value && ..., AllowCopy, DisallowCopy>::type
where AllowCopy
is empty and DisallowCopy
has deleted copy operations (among other things). I also check for default c'tible allocator, and all of this is still not quite right, e.g. I support neither allocator propagation on copy nor copying of elements in the allocator.– Arne Vogel
1 hour ago
2
2
is_nothrow_move_constructible_v<Node>
is false
in MSVC, so it tries to copy and fails; it is true
in gcc, so it moves. If is_nothrow_move_constructible_v<Node>
is forced to become false
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree on is_nothrow_move_constructible_v<Node>
value?– Evg
33 mins ago
is_nothrow_move_constructible_v<Node>
is false
in MSVC, so it tries to copy and fails; it is true
in gcc, so it moves. If is_nothrow_move_constructible_v<Node>
is forced to become false
in gcc, it also tries to copy and fails. Why do MSVC and gcc disagree on is_nothrow_move_constructible_v<Node>
value?– Evg
33 mins ago
 |Â
show 5 more comments
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, otherwise, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible_v
is true
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
libstdc++ implements std::vector
in a similar way, but there std::is_nothrow_move_constructible_v<Node>
is true
in contrast to MSVC, where it is false
. So, move semantics is used and the compiler does not try to generate the copy-constructor.
But if we force is_nothrow_move_constructible_v
to become false
struct Base
Base() = default;
Base(const S&) = default;
Base(Base&&) noexcept(false)
;
struct Node : Base
std::unordered_map<int, std::unique_ptr<int>> map;
;
int main()
std::vector<Node> vec;
vec.reserve(1);
the same error occurs:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 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, otherwise, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible_v
is true
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
libstdc++ implements std::vector
in a similar way, but there std::is_nothrow_move_constructible_v<Node>
is true
in contrast to MSVC, where it is false
. So, move semantics is used and the compiler does not try to generate the copy-constructor.
But if we force is_nothrow_move_constructible_v
to become false
struct Base
Base() = default;
Base(const S&) = default;
Base(Base&&) noexcept(false)
;
struct Node : Base
std::unordered_map<int, std::unique_ptr<int>> map;
;
int main()
std::vector<Node> vec;
vec.reserve(1);
the same error occurs:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 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, otherwise, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible_v
is true
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
libstdc++ implements std::vector
in a similar way, but there std::is_nothrow_move_constructible_v<Node>
is true
in contrast to MSVC, where it is false
. So, move semantics is used and the compiler does not try to generate the copy-constructor.
But if we force is_nothrow_move_constructible_v
to become false
struct Base
Base() = default;
Base(const S&) = default;
Base(Base&&) noexcept(false)
;
struct Node : Base
std::unordered_map<int, std::unique_ptr<int>> map;
;
int main()
std::vector<Node> vec;
vec.reserve(1);
the same error occurs:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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, otherwise, _Uninitialized_copy
is called.
The problem is that the type trait std::is_copy_constructible_v
is true
for Node
if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.
libstdc++ implements std::vector
in a similar way, but there std::is_nothrow_move_constructible_v<Node>
is true
in contrast to MSVC, where it is false
. So, move semantics is used and the compiler does not try to generate the copy-constructor.
But if we force is_nothrow_move_constructible_v
to become false
struct Base
Base() = default;
Base(const S&) = default;
Base(Base&&) noexcept(false)
;
struct Node : Base
std::unordered_map<int, std::unique_ptr<int>> map;
;
int main()
std::vector<Node> vec;
vec.reserve(1);
the same error occurs:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
edited 42 mins ago
answered 2 hours ago


Evg
3,41811334
3,41811334
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 mins ago
add a comment |Â
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 mins ago
1
1
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours ago
Im wondering as to why the issue is not seen with clang or gcc ?
– darune
2 hours 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
2 hours 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
2 hours 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
2 hours 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
2 hours ago
@darune, yes, the code in my answer is directly from MSVC STL implementation. I agree that it feels like a bug.
– Evg
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
1 hour ago
@darune, added some info about in libstdc++.
– Evg
51 mins ago
@darune, added some info about in libstdc++.
– Evg
51 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-explicit-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
5 hours ago
I can confirm this code fails with error code under vs2017 15.4.2.
– marcinj
5 hours ago
Confirm also in the VS2017 15.9.0 Preview 3.
– Evg
5 hours ago