I'm on Visual Studio 2017. Recently, because I didn't like the non-conforming standards to C++ I went ahead and disabled the non-standard language extensions in the options. So far so good. Now I have a problem.
#include <iostream>
#include <vector>
struct Vertex
{
Vertex(float pos) { }
Vertex(Vertex& other) { }
};
std::vector<Vertex> arrayOfVertices;
int main()
{
arrayOfVertices.emplace_back(7.f);
}
This would not compile in Visual Studio, the only error it gives is:
"an internal error has occurred in the compiler"
If I enable the language extensions it compiles fine. If I keep the language extensions disabled and make the copy constructor take a const Vertex&
it compiles fine.
So I tried on GCC on some online compilers and if the copy constructor doesn't take a const reference argument it won't compile, giving various errors. The one that seemed to make the most sense was:
error: invalid initialization of non-const reference of type ‘Vertex&’ from an rvalue of type ‘Vertex’
I thought that copy constructors didn't have to be const, in my case I would like to modify something in the other reference. I know that non-const arguments can't take r-value references, but I tested it and it turns out that in vector::emplace_back()
the copy constructor isn't called at all:
#include <iostream>
#include <vector>
struct Vertex
{
Vertex(float pos)
{
std::cout << "Calling constructor\n";
}
Vertex(const Vertex& other)
{
std::cout << "Calling copy constructor\n";
}
};
std::vector<Vertex> arrayOfVertices;
int main()
{
arrayOfVertices.emplace_back(7.f); // Normal constructor called if const,
// doesn't compile if non-const
auto buff = malloc(sizeof(Vertex)); // Placement new
new (buff) Vertex(7.f); // Normal constructor called whether const
// or non-const. This is what I thought emplace_back did
}
So I have no idea what's going on. I would like to know firstly why this is happening if the copy constructor isn't being called, and also if there's a way to take a non-const in my copy constructor in this case, that is, using vector::emplace_back()
, because it seems this problem is arising only using vector::emplace_back()
.
/Za
switch is poorly tested and not really supported by the standard library. – Strychninemutable
class members may be a slightly better solution to whatever motivation you have to do this – Linetta/permissive-
flag. – Plevenstd::move(old-value)
. That's not going to bind to a non-const reference. What sort of changes do you want to make in the previous value? You might be better off with a move constructor. – Tope