Reputation: 8591
I have a matrix class (the element type is Y
) that has, along with other constructors, the following constructor:
matrixT(
size_type rows, // The number of rows
size_type cols // The number of columns
) :
boost::numeric::ublas::matrix<Y>(rows, cols)
{
}
(I use boost BLAS for the actual implementation, but that's not relevant here).
I need a std::vector<matrixT>
of this (for Y
a double
), and I know how many elements I need; n
, say. I also know all the sizes in advance; all have rows
rows and cols
columns
I'd like to do something like
std::vector<matrixT> vec(n, std::emplace(rows, cols))
as I'd like to avoid taking deep copies of such matrices. My understanding is I can do something to force the constructor to be called; which is what std::emplace(rows, cols)
is there for.
However I can't get the syntax correct. Any ideas? Do I need to use std::initialiser_list
?
(If my terminology is incorrect then please feel free to let me know, or edit the question).
Upvotes: 3
Views: 327
Reputation: 275555
Here is an emplace_n
and emplace_create_vector
:
template<class... Ts,class...Args>
void emplace_n( std::vector<Ts...>& vec, size_t n, Args&&... args ) {
if (vec.capacity() < vec.size() + n ) {
vec.reserve( (std::max)(vec.capacity()*3/2, vec.size()+n) );
}
for (size_t i = 1; i < n; ++i) {
vec.emplace_back(args...);
}
if (n)
vec.emplace_back(std::forward<Args>(args)...);
}
template<class...Ts,class...Args>
std::vector<Ts...> emplace_create_vector( size_t n, Args&&... args ) {
std::vector<Ts...> retval;
emplace_n( retval, n, std::forward<Args>(args)... );
return retval;
}
This lets you create an n-element vector via emplacement, instead of copying.
std::vector<matrixT> vec = emplace_create_vector<matrixT>(n, rows, cols);
and it does so reasonably efficiently.
Every vector
copy above will be elided by any acceptable C++ compiler, and no copy or move constructor of matrixT
is called.
Upvotes: 2
Reputation: 234715
There's no need for std::vector
to have such a constructor.
It already provides a method called emplace_back
. The arguments of emplace_back
should match the arguments of one of your constructors.
vec.emplace_back(rows, cols)
called n
times will achieve what you want without taking a deep copy of the matrix. You could even reserve
vector storage in advance.
(std::initializer
list - note the spelling - is used for brace initialisation; a different topic).
Upvotes: 4