Reputation: 9635
I tried to initialize the std::vector
std::vector<Particle> particles;
with instances of the simple struct
struct Particle {
int id;
double x;
double y;
double theta;
double weight;
};
by using emplace with an initializer list:
num_particles = 1000;
for (int i = 0; i < num_particles; i++)
{
particles.emplace_back({ i,0.0,0.0,0.0,1 });
}
But I get the error
C2660 "std::vector>::emplace_back": Function doesn't accept one argument
How can I fix that?
Upvotes: 13
Views: 15781
Reputation: 3591
std::vector::emplace
expects an iterator as argument too, because it inserts the element before that iterator's position.
Another problem is that your {i, 0.0, 0.0, 1}
initialization doesn't work because it isn't in a context which tells what type it needs to instantiate. The reason there isn't any context is due to emplace
and emplace_back
member functions having generic parameters.
If you just want to append elements to the vector, use emplace_back
.
However, emplace_back
depends on the element type having a valid constructor in order to work, as the element is initialized through parentheses. That changed in C++20, which now allows aggregate-initialization through parentheses without the need to define a valid constructor.
So, up until C++17, your example would be changed to:
for (int i = 0; i < num_particles; ++i)
particles.push_back({i, 0.0, 0.0, 1});
And in C++20 and later, you may do this instead:
for (int i = 0; i < num_particles; ++i)
particles.emplace_back(i, 0.0, 0.0, 1);
Upvotes: 16
Reputation: 2709
You have several issues with your code:
Emplace takes an iterator as insertion point, and then a list of values which serve as arguments to a constructor.
Your struct must have a constructor which takes the values you pass to emplace.
You only have 4 argument values in your code, but your Particle
struct has 5 fields.
Try this code instead:
struct Particle {
int id;
double x;
double y;
double theta;
double weight;
Particle(int id, double x, double y, double theta, double weight)
: id(id), x(x), y(y), theta(theta), weight(weight)
{
}
};
Notice the constructor there. And then emplace, for instance in the beginning [just an example which is not inserting at the back (see below)]:
std::vector<Particle> particles;
auto num_particles = 1000;
for (int i = 0; i < num_particles; i++)
{
particles.emplace(particles.begin(), i, 0.0, 0.0, 1.0, 0.0);
}
As others have noted, if you just want to insert without specifying a specific position in the vector, you can use emplace_back
:
std::vector<Particle> particles;
auto num_particles = 1000;
for (int i = 0; i < num_particles; i++)
{
particles.emplace_back(i, 0.0, 0.0, 1.0, 0.0);
}
This inserts the elements at the end of the vector.
Upvotes: 10
Reputation: 21576
First, std::vector::emplace
requires the first argument passed to be an iterator representing the position where the element should be inserted.
Secondly, even if you provide the position. Template types are not deduced for initializer_lists. See initializer_list and template type deduction. So, below will equally fail:
particles.emplace( particles.end(), {i, 0.0, 0.0, 1, 1});
Since there is no constructor that can take the initializer list, below will likewise fail:
particles.emplace( particles.end(), i, 0.0, 0.0, 1, 1);
You either use insert
or push_back
as in:
particles.insert( particles.end(), {i, 0.0, 0.0, 1, 1});
particles.push_back({i, 0.0, 0.0, 1, 1});
or emplace or push_back:
particles.emplace( particles.end(), Particles{i, 0.0, 0.0, 1, 1});
particles.emplace_back(Particles{i, 0.0, 0.0, 1, 1});
Upvotes: 4