简体   繁体   中英

Using emplacement to construct a vector of matrices of constant size

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).

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).

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;
}

live example

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM